Odczyt UNICODE

0

<font size="2">Mam do napisania program, który będzie kopiował zawartość danego pliku tekstowego do innego pliku tekstowego.</span>

W tym celu kolejno:

  1. otwieram plik;
  2. zliczam ilość znaków w pliku;
  3. alokuję odpowiednią ilość pamięci (tablicę znaków o odpowiedniej długości);
  4. czytam plik znak po znaku i zapisuje kolejne znaki do tablicy;
  5. tworze nowy plik;
  6. przepisuje kolejno znak po znaku wszystkie znaki z tablicy do nowego pliku.

Problem jest w tym, że dla niektórych plików ten algorytm działa, a dla niektórych nie.
Podejrzewam, że pliki, dla których algorytm nie działa są zakodowane w UNICODE.
Po czym poznać, czy plik zapisuje znaki na 8, czy na 16 bitach i jak obsłużyć ten drugi sposób zapisu?

Oto program, który działa dla plików zapisanych w ASCII:

#include <iostream>
#include <string>
#include <conio.h>
#include <stdlib.h>
#include <fstream>
#include <stdio.h>

using namespace std;

int main()
{
   char* napis;
   char nazwa[256];
   int l = 0;
   fstream plik, plik1, plik2;

   cout << "Podaj nazwe pliku: ";
   cin >> nazwa;

   plik1.open(nazwa, ios::in);
   /* obliczam ilosc znakow w pliku */
   while(plik1.eof() == 0)
   {
      plik1.get();
      l++;
   }
   plik1.close();

   /* alokuje odpowiednio dluga tablice znakow */
   napis = new char[l];
   cout << "Plik zawiera " << l << " znakow." << endl;
   l = 0;

   plik.open(nazwa, ios::in);
   /* zczytuje wszystkie znaki do tablicy */
   while(plik.eof() == 0)
   {
      plik.get(napis[l]);
      l++;
   }
   plik.close ();

   /* tworze nowa nazwe pliku */
   strcat(nazwa, "_new.txt");

   /* zapisuje zawartosc tablicy do nowego pliku */
   plik2.open(nazwa, ios::out);
   for(int i = 0; i < l-1; i++)
   {
      plik2.put(napis[i]);
   }
   plik2.close();
   getch();

   return 0;
}

Pliki testowe:

Dla tego pliku program działa:http://free.of.pl/s/szachysta/plik1.txt
Dla tego pliku program nie działa:http://free.of.pl/s/szachysta/plik2.txt

Problem polega na tym, że muszę napisać program, który powinien obsłużyć wszystkie możliwe formaty plików tekstowych,
czyli program sam musi sprawdzać jak plik jest zapisany i obsłużyć go w odpowiedni sposób.

Proszę o pomoc, bo bez rozwiązania tego problemu nie mogę ruszyć dalej z pisaniem programu, którego ten problem jest niestety częścią...

--
Szach

0

Po czym poznać, czy plik zapisuje znaki na 8, czy na 16 bitach i jak obsłużyć ten drugi sposób zapisu?

Po pierwszych bajtach:

0xFE 0xFF               - UTF-16
0xFF 0xFE               - byte-swapped UTF-16
0x00 0x00 0xFE 0xFF     - UTF-32
0xFF 0xFE 0x00 0x00     - byte-swapped UTF-32 
0xEF 0xBB 0xBF          - UTF-8
0xDD 0x73 0x73 0x73     - UTF-EBCDIC 
0x0E 0xFE 0xFF          - SCSU (recommended; others are possible)
0
0x666 napisał(a)

Po czym poznać, czy plik zapisuje znaki na 8, czy na 16 bitach i jak obsłużyć ten drugi sposób zapisu?

Po pierwszych bajtach:

[cutted some part of the post]

A mógłbym prosić o jakiś przykład obsłużenia tych innych niż UTF-8... ?
(bo rozumiem, że kod, który napisałem wyżej obsługuje UTF-8)

--
Szach</quote>

0

Zasadniczo to nie wiem po co te całe rozróżnianie kodowania przecież chcesz tylko zduplikować plik. Potraktuj ten plik jak każdy inny nietekstowy i skopiuj go przy użyciu metod read i write.

(bo rozumiem, że kod, który napisałem wyżej obsługuje UTF-8)

Nie, UTF-8 to UNICODE, a Twój kod obsługuje tylko ANSI. W UTF-8 litera może zająć od 1 do 4 bajtów więc... ;) Podobnie z UTF-16 - od 2 to 4 bajtów.

0

uzyj iconva i po problemie :P

0

<font size="2">Ok, więc napiszę o co dokładnie chodzi.</span>

Muszę odczytać zawartość pliku, znaleźć w nim zadany ciąg znaków i zamienić na inny (niekoniecznie tej samej długości),
więc muszę wczytać cały plik do pamięci, zamienić stringi i zapisać do innego pliku.
Myślę sobie, że dosyć łatwo będzie zaimplementować listę znaków i w taki sposób działać na zawartości pliku,
bo z listy łatwo można usuwać i dodawać węzły (węzeł = obiekt reprezentujący pojedynczy znak).

Dlatego MUSZĘ umieć czytać każdy rodzaj pliku tekstowego i tak zaimplementować listę,
żeby można było w jej węzłach przechować każdy możliwy znak.

Właśnie czytam to: http://www.gnu.org/software/libiconv/

<font size="2">Dzięki za dotychczasowe wskazówki!</span>

A może jest jakiś lepszy sposób przetwarzania plików tekstowych niż lista znaków?

--
Szach

0

Bez przesady...

A może jest jakiś lepszy sposób przetwarzania plików tekstowych niż lista znaków?

Lista napisów ?
C/C++ oferuje funkcje i odpowiednie typy do operacji na stringach zawierających znaki szerokie .

0
dzejo napisał(a)

Lista napisów ?

Chyba wyrazów ;)

C/C++ oferuje funkcje i odpowiednie typy do operacji na stringach zawierających znaki szerokie .

Jeżeli mowa o wstring to nie do końca...

PS. jeżeli to jest jakieś zaliczenie to wątpię, żeby wymagana była obsługa unikodu.

0
0x666 napisał(a)

PS. jeżeli to jest jakieś zaliczenie to wątpię, żeby wymagana była obsługa unikodu.

Niestety muszę obsłużyć unicode, a dokładnie program musi działać dla każdego
możliwego pliku tekstowego zapisanego w systemie Windows.

Mam jeszcze problem z tym, jak sprawdzić, czy dany plik w ogóle nadaje się
do przetwarzania takim programem, bo może się zdarzyć, że plik nie jest tekstowy...
Wtedy wypadałoby wypisać jakiś komunikat.

Jak to sprawdzić? Jak odróżnić pliki tekstowe od nietekstowych?

<font size="2">Uogólniając algorytm powinien wyglądać tak:</span>

1. Sprawdź, czy dany plik jest plikiem tekstowym;
a. Jeśli nie jest plikiem tekstowym to wypisz komunikat i zakończ działanie programu;
b. Jeśli jest plikiem tekstowym to znajdź w nim zadany ciąg znaków i zamień na inny zadany ciąg znaków.

Co do podpunktu b to na razie mam mętlik w głowie...

[???]

--
Szach

0

666

Chyba wyrazów

wyrazów, wyrazów .. [green]

Zamiast marudzić jak stare baby to może ktoś poda jakiś kod ?
Że tak zacytuję sam siebie :

C/C++ oferuje funkcje i odpowiednie typy do operacji na stringach zawierających znaki szerokie .

Moze ktoś mi wyjaśni dlaczego to g.. nie działa .
Dla pliku :
http://free.of.pl/s/szachysta/plik2.txt

#include <fstream.h>
#include <stdio.h>

//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char **argv)
{
wchar_t tab[256] ; //=L"Napis" ;
char znak ;

FILE*plik ;
plik = fopen("plik2.txt","r") ;
 if(!plik)
 {

  printf("Error");
  getchar();
  return 0 ;
 }

 fscanf(plik,"%c",&znak);  // usuwamy Znacznik typu pliku.
 fscanf(plik,"%c",&znak);

 while(EOF != fwscanf(plik,L"%s",tab) )    // scanf dla znaków wchar_t
 {
  wprintf(L"%s\n",tab);                           // printf dla wchar_t
 }
fclose(plik);
getchar();
        return 0;
}

Plik jest czytany poprawnie do końca wiersza , a następnie 'fwscanf' się zawiesza
i wywala program .

Program napisany dla pliku Nie-Unicode działa poprawnie
funkcje fscanf i printf .

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0