БлогNot. Visual C++: почему не сохраняется файл? :)

Visual C++: почему не сохраняется файл? :)

Типовое мучение новичков - загрузили картинку в PictureBox, например,

Image ^ Img = gcnew Bitmap("123.jpg");
pictureBox1->Image = Img;

затем что-то с ней сделали и хотим сохранить обратно. Увы, ничего не выходит, а системное сообщение об ошибке гласит лишь:

В GDI+ возникла ошибка общего вида.

Ну и с другими компонентами бывает подобное же. Нетрудно догадаться, в чём состоит проблема - просто файл, который мы хотим переписать, всё ещё остаётся открытым и возникает ошибка совместного доступа. Многие упрощенные методы работы с файлами из GDI+ блокируют доступ к файлам. Такие методы имеет смысл использовать только для одноразовых файловых операций (когда нужно один раз прочитать или записать данные, и не более того).

Если вы собираетесь переписывать файл, то так, как показано ниже, делать не нужно, всё откроется, но при переписывании получите проблему:

openFileDialog1->ShowDialog();
if (openFileDialog1->FileName != "" && openFileDialog1->FileName != nullptr) {
 Image ^ Img;
 try {
  Img = gcnew Bitmap(openFileDialog1->FileName);
 }
 catch (Exception^ e) {
  System::Windows::Forms::MessageBox::Show(e->Message + "\nНе удалось открыть файл", "Ошибка",
   MessageBoxButtons::OK, MessageBoxIcon::Exclamation);
  return;
 }
 pictureBox1->Image = Img;
}

Теперь попытка переписать файл обычными средствами

try {
 pictureBox1->Image->Save(openFileDialog1->FileName); //Сохраняем под именем из диалога открытия файла
 //или вместо этой строки 2 строки ниже:
 //Bitmap ^bitmap1 = gcnew Bitmap(pictureBox1->Image);
 //bitmap1->Save (openFileDialog1->FileName); 
} 
catch (Exception^ e) {
 MessageBox::Show(e->Message + "\nНе удалось сохранить файл", "Ошибка",
  MessageBoxButtons::OK, MessageBoxIcon::Exclamation);
 return;
}

приведёт лишь к показанной выше ошибке. Часто рекомендуемое в инете

delete pictureBox1->Image; pictureBox1->Image = nullptr;

- аналог работающего в C#

pictureBox1.Image.Dispose();

на C++ не поможет.

А решение таково: для нормальных операций с файлами используйте FileStream, чтобы контролировать весь процесс.

Вот правильная версия кода для открытия файла:

openFileDialog1->ShowDialog();
if (openFileDialog1->FileName != "" && openFileDialog1->FileName != nullptr) {
 System::IO::FileStream ^ file;
 try {
  file = gcnew System::IO::FileStream(openFileDialog1->FileName, System::IO::FileMode::Open, 
   System::IO::FileAccess::Read, System::IO::FileShare::Inheritable);
 }
 catch (Exception^ e) {
  System::Windows::Forms::MessageBox::Show(e->Message + "\nНе удалось открыть файл", "Ошибка",
   MessageBoxButtons::OK, MessageBoxIcon::Exclamation);
  return;
 }
 pictureBox1->Image = Image::FromStream(file);
 file->Close();
}

Теперь показанное выше сохранение файла под тем же именем, под которым он был открыт, работает в любой из 2 версий операторов сохранения.

07.10.2015, 16:24 [7938 просмотров]


теги: программирование ошибка studio c++/cli

К этой статье пока нет комментариев, Ваш будет первым