четверг, 6 марта 2008 г.

Грузим текстовый файл

Задача: есть wxTextCtrl, пользователь должен уметь загружать в него свои текстовые файлы для просмотра и редактирования, своего рода notepad. Файлы у пользователя могут быть в ANSI, utf-8 и в одном из двух юникодов.

Есть wxTextCtrl::LoadFile() - думаю зашибись, повезло. Тестирую, юникод\утф-8 грузит, ANSI грузит только если там одни английские символы, если есть русские обламывается. Нахожу? что проблема в дебрях библиотеки, в попытке грузить файл как wxFFile::ReadAll(wxString * str, wxMBConv& conv = wxConvUTF8)

Спрашиваю в wx-dev@, вот ответ

TN> Is this a bug? If no, is there a any way to load ANSI files in unicode
TN> build?

Yes, use wxCSConv(wxFONTENCODING_CP1251) instead of default wxConvAuto
which only handles UTF-x encodings in 2.8 (in the trunk it falls back to
the system default encoding if the input doesn't seem to be in UTF-8, but
not in 2.8).

Баг это или нет, я так и не понял. Но понял что wxTextCtrl::LoadFile() использовать нельзя, так как кодировку там задать нет возможности. Пришлось использовать напрямую wxFFile, с шаманством. Вот функция для загрузки файла

bool BegUtils::ReadFileToString(const wxString & FileName, wxString & Data)

{

wxFFile file(FileName);

if (!file.IsOpened() ) return false;

// пытаемся читать файл подразумевая что он юникодный

if (!file.ReadAll(&Data)) return false;

if (Data.IsEmpty() && file.Length()>0)

{ // Если строка пустая и длина у файла есть - то он наверняка был анси, читаем как анси

file.Seek(0);

if (!file.ReadAll(&Data, *wxConvCurrent)) return false;

}

return true;

}


Вроде как работает, правда будут проблемы при загрузки пустых юникодных файлов - на экране будет мусор (BOM), можно конечно проверять загруженную строку на равенство одному из них, но я забил.

Подозреваю что это довольно кривой метод, поэтому если кто знает как решить задачу "правильно", с удовольствием послушаю.

5 комментариев:

Анонимный комментирует...

Николай, что-то у меня в Опере в этой записи некоторое строки отображаются некорректно, в частности строка "Баг это или нет, я так и не понял. Но понял что wxTextCtrl::Load" здесь и заканчивается. В Firefox отображается корректно.

Может быть, там тэг где-нибудь незакрытый?

Анонимный комментирует...

Да, похоже что WLW не идеал:( вроде подправил. Так нормально?

Анонимный комментирует...

Ага, сейчас, вроде, все нормально.

Спасибо.

Pretorean комментирует...

а что скажешь про такое извращение ? )))
это если файл внутри виртуальной файловой системы ...

wxString MainFrame::OpenFileToString(wxString location)
{
wxFileSystem fs;
wxFSFile *fsfile = fs.OpenFile(location);
wxInputStream *stream = fsfile->GetStream();
wxTextInputStream text ( *stream);
wxString result;
while (!stream->Eof())
{
result += wxString(text.ReadLine() + wxT("\n"));
}
return result;
}

Анонимный комментирует...

А чего говорить, вроде нормально все, извращением не пахнет:)
Я правда с виртуальной фс не работал, да и с потокоми не очень.