String mit ReadFile lesen



  • Hallo Leute.

    Ich möchte einen Unicode-String auslesen.

    Dazu habe ich was vorbereitet, funktioniert aber nicht!
    Der LPWSTR enthält nur hyroglyphen. Das kann damit zusammenhängen, dass ein WCHAR multiple-byte ist und die textdatei nicht. aber wie lese ich denn nun vernünftig aus? und zwar u8nbedingt mit der nativen winapi!

    void LoadFilter(HINSTANCE hInstance, LPWSTR lpFilter)
    {
    	WCHAR name[MAX_PATH + 1];
    	LoadString(hInstance, IDS_FILTER, name, MAX_PATH);
    
    	// build path to read file
    	WCHAR path[MAX_PATH + 1];
    	GetModuleFileName(NULL, path, MAX_PATH);
    	PathRemoveFileSpec(path);
    	PathAppend(path, name);
    
    	HANDLE hFile = CreateFile(path,
    							  GENERIC_READ|GENERIC_WRITE,
    							  FILE_SHARE_READ,
    							  NULL,
    							  OPEN_EXISTING,
    							  FILE_ATTRIBUTE_NORMAL,
    							  NULL);
    
    	if (hFile == INVALID_HANDLE_VALUE)
    	{
    		lpFilter[0] = L'\0';
    		return;
    	}
    
    	WCHAR buffer[MAX_READ_FILTER + 1];
    	DWORD dwRead;
    
    	if (!ReadFile(hFile, buffer, MAX_READ_FILTER, &dwRead, NULL))
    	{
    		lpFilter[0] = L'\0';
    		return;
    	}
    
    	lstrcpy(lpFilter, buffer);
    
    	CloseHandle(hFile);
    }
    

    Vielen Dank schonmal.



  • Was denn?
    Hat denn keiner ne Ahnung?
    Oder liest man Texte generell nicht mit ReadFile aus?

    Fakt ist, ich benötige ein LPWSTR, egal ob die Textdatei ein Ansi- oder Unicode-Format hat oder was auch immer.

    Danke.



  • MultiByteToWideChar



  • Gut, danke. Aber was, wenn die Text-Datei ein ANSI-File ist, wie überprüft man das?





  • Normalerweise haben Unicode-Textdateien eine Markierung. Wenn keine da ist, dann ist es eine Ansi- oder ASCII-Datei.



  • Danke. Könntet ihr meinen COde so abbessern, dass er überprüft, um welches Format es sich handelt? Ich komme mit diesem "big endian" oder so net klar...
    Danke.



  • Könntet ihr meinen COde so abbessern, dass er überprüft, um welches Format es sich handelt?

    nein



  • na gut, ihr habt ja recht...

    ich habe jetzt mal was selber versucht, das funktioniert auch mit ANSI, UTF-8, UNICODE, aber eben nicht mit UNICODE big endian.

    void LoadFilter(HINSTANCE hInstance, LPWSTR lpFilter)
    {
    	WCHAR name[MAX_PATH + 1];
    	LoadString(hInstance, IDS_FILTER, name, MAX_PATH);
    
    	// build path to read file
    	WCHAR path[MAX_PATH + 1];
    	GetModuleFileName(NULL, path, MAX_PATH);
    	PathRemoveFileSpec(path);
    	PathAppend(path, name);
    
    	HANDLE hFile = CreateFile(path,
    							  GENERIC_READ|GENERIC_WRITE,
    							  FILE_SHARE_READ,
    							  NULL,
    							  OPEN_EXISTING,
    							  FILE_ATTRIBUTE_NORMAL,
    							  NULL);
    
    	if (hFile == INVALID_HANDLE_VALUE)
    	{
    		lpFilter[0] = L'\0';
    		return;
    	}
    
    	char buffer[MAX_READ_FILTER * sizeof(WCHAR) + 1];
    	DWORD dwToRead = MAX_READ_FILTER * sizeof(WCHAR) + 1;
    	DWORD dwRead;
    
    	if (!ReadFile(hFile, buffer, dwToRead, &dwRead, NULL))
    	{
    		lpFilter[0] = L'\0';
    		return;
    	}
    
    	WCHAR filter[MAX_READ_FILTER + 1];
    
    	if (buffer[0] >= 0) // ansi
    	{
    		MultiByteToWideChar(CP_ACP,
    							0,
    							buffer,
    							sizeof(buffer),
    							filter,
    							MAX_READ_FILTER);
    	}
    	else if (buffer[0] == -17) // utf-8
    	{
    		MultiByteToWideChar(CP_UTF8,
    							0,
    							buffer+1,
    							sizeof(buffer)-1,
    							filter,
    							MAX_READ_FILTER);
    	}
    	else if (buffer[0] == -1) // unicode
    	{
    		memcpy(filter, buffer+2, sizeof(buffer)-2);
    	}
    	else if (buffer[0] == -2) // unicode big endian
    	{
    		// was soll ich denn hier machen?
    		// das memcpy vom unicode gibt nur hyroglyphen.
    	}
    
    	MessageBox(NULL, filter, NULL, MB_OK);
    
    	CloseHandle(hFile);
    }
    

    Was soll ich in die auskommentierte stelle reinpacken? Wie soll ich das machen?

    Danke.



  • du könntest einfach die 2 bytes eines words tauschen.
    davon abgesehen würde ich auch das 2. byte des byte-order-markers prüfen.



  • Viele Unicode-Dateien haben gar keinen BOM. Auch die Funktionen im .net-framework z.B. schreiben per-default keinen BOM.



  • Warum das 2.?

    lohnt es sich, beide zu prüfen?

    Welche daten haben die des 2.?

    Danke.



  • Warum das 2.?
    lohnt es sich, beide zu prüfen?
    Welche daten haben die des 2.?
    Danke.

    http://en.wikipedia.org/wiki/Byte_Order_Mark

    Und wenn kein BOM vorhanden ist kann man nurnoch versuchen "gut zu raten", oder den User zu fragen.



  • jetz hab ich hier hex-zahlen.

    Ist es besser == 0xEF zu überprüfen, als mit den Zahlen?



  • das habe ich jetzt:

    if ((buffer[0] == -17) && (buffer[1] == -69)) // utf-8
    	{
    		MultiByteToWideChar(CP_UTF8,
    							0,
    							buffer+3,
    							sizeof(buffer)-3,
    							filter,
    							MAX_READ_FILTER);
    	}
    	else if ((buffer[0] == -1) && (buffer[1] == -2)) // unicode
    	{
    		memcpy(filter, buffer+2, sizeof(buffer)-2);
    	}
    	else if ((buffer[0] == -2) && (buffer[1] == -1)) // unicode big endian
    	{
    		for (int i = 2; i < sizeof(buffer); i+=2)
    		{
    			// swap bytes
    			char buff = buffer[i];
    			buffer[i] = buffer[i + 1];
    			buffer[i + 1] = buff;
    		}
    		memcpy(filter, buffer+2, sizeof(buffer)-2);
    	}
    	else
    	{
    		MultiByteToWideChar(CP_ACP,
    							0,
    							buffer,
    							sizeof(buffer),
    							filter,
    							MAX_READ_FILTER);
    	}
    

    Auf Raten kein bock, wenn das nicht ordnungsgemäß gemacht wird, haben die pech gehabt...

    danke.



  • Jo sieht nicht ganz verkehrt aus.
    Was die Hexzahlen angeht: wenn's nur mit MSVC und einstellung "default char unsigned = false" gehen soll dann müsste das so passen.
    Ansonsten vielleicht lieber "(int(buffer[0]) & 0xFF) == 0xFF" oder sowas verwenden.


Anmelden zum Antworten