Windows API, odczyt pliku tekstowego

0

Hej! Mam problem z odczytem pliku tekstowego przy użyciu Windows API (piszę bibliotekę DLL i mi jest potrzebny odczyt plików txt)
Funkcja wygląda tak :

LPSTR OdczytajZawartoscPliku(LPCTSTR fileName)
{
HANDLE hFile; 
DWORD  dwBytesRead = 0;
char  ReadBuffer[BUFFERSIZE] = {0};
LPSTR ZawartoscPlikuTekstowego = NULL;
hFile = CreateFile(fileName,               
                       GENERIC_READ,          
                       FILE_SHARE_READ,      
                       NULL,                  
                       OPEN_EXISTING,         
                       FILE_ATTRIBUTE_NORMAL, 
                       NULL);                
 
    if (hFile == INVALID_HANDLE_VALUE) 
    { 

		MessageBox(NULL, TEXT("Nie można otworzyć pliku! "), TEXT("Błąd"), MB_OK | MB_ICONERROR);
        return NULL; 
    }



    if( FALSE == ReadFile(hFile, ReadBuffer, BUFFERSIZE-1, &dwBytesRead, NULL) )
    {

		MessageBox(NULL, TEXT("Nie można przeczytać zawartości pliku! "), TEXT("Błąd"), MB_OK | MB_ICONERROR);
        CloseHandle(hFile);
        return NULL;
    }


    if (dwBytesRead > 0 && dwBytesRead <= BUFFERSIZE-1)
    {
        ReadBuffer[dwBytesRead]='\0'; // NULL character

        //_tprintf(TEXT("Data read from %s (%d bytes): \n"), argv[1], dwBytesRead);
        printf("%s\n", ReadBuffer);
    }
    else if (dwBytesRead == 0)
    {
		MessageBox(NULL, TEXT("Zawartość pliku jest pusta! "), TEXT("Błąd"), MB_OK | MB_ICONERROR);
    }
    else
    {
		MessageBox(NULL, TEXT("Niespodziewana wartość w dwBytesRead! "), TEXT("Błąd"), MB_OK | MB_ICONERROR);
    }


    // zamknięcie uchwytu pliku
    CloseHandle(hFile);
	ZawartoscPlikuTekstowego = ReadBuffer;
	MessageBoxA(NULL, ReadBuffer, "Informacja", MB_OK | MB_ICONINFORMATION); // tutaj jest ok wyswietlane 
	MessageBoxA(NULL, ZawartoscPlikuTekstowego, "Informacja", MB_OK | MB_ICONINFORMATION); // tutaj tez ok
	return ZawartoscPlikuTekstowego;
	
}

 

Wewnątrz funkcji wszysztko ok. Jak funkcje wywołam z innego pliku to już się krzaczy np : w pliku głównym :

MessageBoxA(NULL, OdczytajZawartoscPliku(szPelnaSciezkaZPlikem), "Informacja", MB_OK | MB_ICONINFORMATION);

to już nic nie pokazuje.... Tzn puste okienko...
Problem z konwersja z ANSI?
Czy może lepiej użyć standardowych funkcji C++ do odczytu zawartości plików tekstowych?

0

Skoro używasz runtime C++ to nie ma chyba powodu, dla którego nie możesz użyć go do odczytania plików?

ps. jeżeli piszesz nieprzenośny kod korzystający z Windows API to używaj Unicode albo pisz kod, który będzie działał dla obu ustawień.

0

A ta funkcja do odczytu plików to dla unikodów ? Już się zamotałem ...

0

Która funkcja? Jakie kodowanie? Może napisz co chcesz osiągnąć (czytać bajty czy znaki? chcesz tekstem manipulować przy użyciu któregoś z API?) i jakie pliki chcesz odczytać (jakie kodowania mają?).

0

Chodzi o to, że jeśli w wewnątrz funkcji odczytam zawartość pliku tekstowego to jest ok, natomiast jeśli chce tą zmienną z zawartością tekstu zwrócić poza funkcje to są krzaki... typy danych się zgadzają...

1

Zwracasz wskaźnik do lokalnej tablicy. Utwórz ją na stercie (malloc/new). Pamiętaj później, żeby zwolnić tę pamięć albo użyj inteligentnych wskaźników.

0

Ale tą tablicę utworzyć wewnątrz funkcji? Bo jeśli po return ją zwolnię operatorem delete po wyrażeniu return to delete się nie wykona... Sorki, za głupie pytania... ale dawno nie bawiłem się wskaźnikami...

0

Co to za pomysł żeby pisać cokolwiek po return?
Użyj po prostu delete gdy wskaźnik już nie będzie potrzebny. Niekoniecznie w funkcji, która alokuje pamięć.

0

tzn. mam zwrócić wskaźnik do LPSTR ZawartoscPlikuTekstowego ? Przeskoczyłem z C# do C++ i trochę już mi się miesza... :/

1

Prawdopodobnie nie... Jest masa sposobów. Ale który wybrać? Zależy od sytuacji której to nie opisałeś.
Są lepsze sposoby na zarządzanie pamięcią. Powyższy należy do tych gorszych. Tak na szybko można twój kod naprawić na 2 sposoby:

  1. Zrobić z bufora zmienną statyczną (nie jest thread-safe, a wynik ważny tylko do następnego wywołania funkcji). Niech wołany zarządza pamięcią.
  2. Nie tworzyć bufora wewnątrz funkcji tylko przyjąć go jako parametr. Niech wołający zarządza pamięcią.
    Tworzenie tu a zwalnianie tam nie jest dobre. Ciężko się debuguje, łatwo o wyciek, skomplikowany kod...

Poza tym w C++ jest klasa do zarządzania pamięcią dla porcji tekstu - std::string

string tekst;
getline(ifstream("nazwapliku.txt"), tekst, '\0');

i mamy tekst z pliku.

0

Dzięki za odpowiedzi... Kurcze, nie sądziłem, że z pozoru tak prosta czynność jak odczytanie zawartości pliku tekstowego przy pomocy Windows API będzie zagmatwane... W sumie API mi było potrzebne do pobrania katalogu domowego użytkownika...
Zmodyfikowałem kod na

 
void OdczytajZawartoscPliku(LPCTSTR fileName,LPSTR *dane)
{
HANDLE hFile; 
DWORD  dwBytesRead = 0;
char  ReadBuffer[BUFFERSIZE] = {0};

hFile = CreateFile(fileName,             
                       GENERIC_READ,          
                       FILE_SHARE_READ,       
                       NULL,                  
                       OPEN_EXISTING,        
                       FILE_ATTRIBUTE_NORMAL, 
                       NULL);                
 
    if (hFile == INVALID_HANDLE_VALUE) 
    { 


		MessageBox(NULL, TEXT("Nie można otworzyć pliku! "), TEXT("Błąd"), MB_OK | MB_ICONERROR);
        return; 
    }

    // Read one character less than the buffer size to save room for
    // the terminating NULL character. 

    if( FALSE == ReadFile(hFile, ReadBuffer, BUFFERSIZE-1, &dwBytesRead, NULL) )
    {

		MessageBox(NULL, TEXT("Nie można przeczytać zawartości pliku! "), TEXT("Błąd"), MB_OK | MB_ICONERROR);
        CloseHandle(hFile);
        return;
    }



    if (dwBytesRead > 0 && dwBytesRead <= BUFFERSIZE-1)
    {
        ReadBuffer[dwBytesRead]='\0'; // NULL character


        printf("%s\n", ReadBuffer);
    }
    else if (dwBytesRead == 0)
    {

		MessageBox(NULL, TEXT("Zawartość pliku jest pusta! "), TEXT("Błąd"), MB_OK | MB_ICONERROR);
    }
    else
    {

		MessageBox(NULL, TEXT("Niespodziewana wartość w dwBytesRead! "), TEXT("Błąd"), MB_OK | MB_ICONERROR);
    }


    // zamknięcie uchwytu pliku
    CloseHandle(hFile);
	*dane = ReadBuffer;

	
	return;
}

no i wywołuje tak w kodzie mojej dll:

LPSTR ZawartoscPlikuTekstowego;
......

OdczytajZawartoscPliku(szPelnaSciezkaZPlikem, &ZawartoscPlikuTekstowego);
MessageBoxA(NULL, ZawartoscPlikuTekstowego, "Informacja", MB_OK | MB_ICONINFORMATION);
return ZawartoscPlikuTekstowego;

 

No i są krzaczki... albo już coś mieszam, albo faktycznie bezpieczniej użyć funkcji z biblioteki standardowej C++
Chodzi mi o to, żeby moja dllka zwróciła wczytany tekst z pewnego pliku...

1

Nie jest zagmatwane. To ty próbujesz nieporadnie za pomocą armaty zabić muchę. Do przeczytania pliku w ogóle nie trzeba używać tych stosunkowo niskopoziomowych funkcji Windows API.
Po to wymyślono bibliotekę standardową C/C++, żeby z nich korzystać. W C# też importujesz CreateFile i ReadFile jak chcesz odczytać plik?

0

W sumie racja.. Ok:) Później to przerobie :) Mam nadzieje, że jakoś uda mi się zwrócić odczytany plik w postaci stringa lub czegoś podobnego i żeby CA Visual Objects rozpoznał ten łańcuch znaków.... Wiem, że typ LPSTR odczytuje na pewno z funkcji DLL importowanych do tego środowiska....

0
LOSMARCELOS napisał(a):

żeby CA Visual Objects rozpoznał ten łańcuch znaków.... Wiem, że typ LPSTR odczytuje na pewno z funkcji DLL importowanych do tego środowiska....
Czy tam jest robiony jakiś marshaling czy po prostu można wymieniać się pamięcią? Aplikacja w CA Visual Objects jest czyjaś czy masz może kontrolę nad kodem po obu stronach? Co z kodowaniem znaków?

0

Hmmm jedną bibliotekę napisaną w .NET (konkretnie jedną funkcję) CA Visual Objects bez problemu wywołuje. Oczywiście po odpowiedniej modyfikacji i przerobieniu na "natywny eksport" funkcji która ma wczytać CA VO. Generalnie można wykorzystywać swoje .NETowe biblioteki w środowiskach poza .NET ale w dość ograniczony sposób. .
Trzeba było użyć dwóch narzędzi, ildasm, ilasm oraz zmodyfikować plik IL oraz zastosować marshalling w eksporce funkcji.
Tutaj jest opis :
http://www.blong.com/Conferences/BorConUK2002/Interop1/Win32AndDotNetInterop.htm#InversePInvoke
oraz
http://keicam.wordpress.com/2008/06/17/eksport-funkcji-dll-w-c/
Akurat w wyniku który zwraca funkcja nie ma polskich znaków. Wynik działania tej funkcji jest wczytywany do typy PSZ w CA Visual Objects... Mam dostęp do kodu źródłowego. Dwie potężne aplikacje bazodanowe są w tym środowisku napisane i jakoś muszę je zaadoptować do współpracy z czytnikami zbliżeniowymi do autoryzacji użytkownika (tak w skrócie pisząc).

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