[C] Przekazywanie stringów ze znakiem "\0" (NULL)

0

Witam.

Mam problem z takim czymś:

char *str;
...
ile_przeczytanych = fread(str, zaalokowana_pamiec, 1, f);

Niestety plik jest binarny (zip) i zawiera znaki "\0" (NULL) przez co:

ile_przeczytanych == zaalokowana_pamiec

ale:

ile_przytanych != strlen(str)

Co zrobić żeby dane były przekazywane w całości? Str ma być użyte w funkcji http://library.gnome.org/devel/libsoup/stable/SoupMessage.html#soup-message-set-request
Może jakaś biblioteka z non-null terminated strings, ale jak to potem przekazać do tej funkcji?

Interesuje mnie TYLKO rozwiązanie w C (nie C++).

0

Wczytane dane raczej w całości są w zaalokowanej pamięci. Funkcja strlen zwraca długość tablicy znaków do pierwszego wystąpienia znaku null, więc jak np. jest string char[] = "Lala\0lala" to stlen zwróci ci że string ma długość 4, a w rzeczywistości ma 9.
W C właśnie znak null oznacza koniec stringa więc tego raczej nie obejdziesz.

Funkcja fread wcale nie musi zwrócić ilosc_przeczytanych == zaalokowanapamiec.
W tym wypadku jak masz:
fread(str,zaalokowana_pamiec, 1,f)

to fread prawdopodobnie zwróci 1, bo zostanie wczytany 1 blok o długości zaalokowana_pamiec.

jakbyś zrobił:

fread(str,1,zaalokowana_pamiec,f)
wtedy fread zwróci ilość wczytanych znaków.

0

Problemem nie jest wczytanie tych danych tylko przekazanie ich dalej (do innej funkcji).
Czy jest może jakaś alternatywa dla typu char, gdzie nie ma znaku "\0" na końcu albo można to jakoś obejść.

0

poza samym ciagiem char* ktory podajesz dalej, podawaj obok niego int/long/lonlong z rozmiarem danych.. prosciej sie nie da. nie wazne jaki typ danych do trzymania bajtow wybierzesz, jezeli zdecydujesz sie na jakis 'specjalny' znak mowiacy o koncu, to ktorys z bajtow w koncu trafi sie rowny temu specjalnemu znakowi - ostatecznie jest tylko 256 mozliwosci. jesli zdecydujesz sie na trzymanie bajtow np. w INT i jako koniec wybierzesz sobie -1 nieosiagalne dla bajtu 0..255 czytanego z pliku, wtopisz, bo bedziesz kazdy jeden bajt trzymac w pamieci jako np. cztery..

trzymanie licznika ilosci danych na boku to jedyne sensowne wyjscie. m.in z tego powodu tworzy sie w C++ klasy typu std::vector, albo w C notorycznie spotykane struktury postaci:

struct paczka
{
    unsigned long size;
    char buffer[];
};

zwroc uwage, ze struktura ta ma pole tablicowe BEZ WYMIARU. jest to dozwolone, o ile jest ono OSTATNIE. w tym momencie, majac char tab[104], mozesz taka 'tablice' 'prezrzutwac' na typ paczka*:

char tab[104];
paczka* pkg = (struct paczka*)tab;

i owo PKG bedzie calkowicie poprawnie zachowywac sie jako struktura majaca 1 INT i char[100]..

0

Jeżeli plik jest binarny, to czytaj do unsigned char* a nie char* i nie używaj strlen ani żadnych innych funkcji do obsługi tekstu.

0

Tylko, że to jest tylko część problemu. Jak pisałem chcę wysłać zapytanie przy użyciu libsoup, konkretnie:
http://library.gnome.org/devel/libsoup/stable/SoupMessage.html#soup-message-set-request (to jest jedna z potrzebnych funkcji).
Istotne parametry:
req_length - próbowałem z wartościami większymi niż strlen() i wtedy dodaje mi do zapytania śmieci
req_body - i tu chcę wrzucić ten plik, ale nie sam tylko w treści tego zapytania np.
"---------1234567890
Content-Type: coś;

[i tu ten plik]"

Oczywiście strcat(), g_strjoin() ucinają dane przy pierwszym "\0".

0

Przeczytaj prosze moj post jeszcze raz i powiedz, co jest w nim niezrozumialego, powodujacego ze nie widzisz rozwiazania..

rozwiazanie Twojego problemu brzmi mniej wiecej tak:

bla = sciezkainazwadopliku
asf = dlugoscpliku(bla)
bufor = przygotujbufor(asf)
plik = fopen(bla)
fread(bufor, 1, asf, plik)
soup_message_set_request(????, "costamcobedziecontenttypem", !!!!, bufor, asf);

przyznam, nie chcialo mi sie czytac czym jest ???? (typu SoupMessage), ale bardzo waznym parametrem jest !!!!, przeczytaj o nim bardzo dokladnie, gdyz z tego powodu moga powstawac smieci, zwlaszcza jezeli ilosc danych jest spora - polecam TAKE, ale STATIC i COPY tez warto przemyslec

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