Skocz do zawartości
ElektronPL_WiTu

Biblioteka SDFat - polskie znaki w nazwach plików

Pomocna odpowiedź

tylko że w arduino byte domyśle jest unsigned. To jak już gdzieś w bibliotece trzeba zamienić zmienną bo 16-bitowy int właśnie domyśle jest "signed"

String filename2 = "";
    byte val = 0;
    int j = 1;
    while (val != 3)
    {
      val = data[j];
      if (val != 3) filename2 += char(val);
      j++;
    }

    long current_pos = 0;
    byte data2[32];
    SdFile myFile2;
    myFile2.open((directory + filename2).c_str(), FILE_WRITE | O_TRUNC);

 

Udostępnij ten post


Link to post
Share on other sites
1 minutę temu, ElektronPL_WiTu napisał:

tylko że w arduino byte domyśle jest unsigned

byte to po prostu skrót do "unsigned char". A char jest akurat w AVR-ach signed.

2 minuty temu, ElektronPL_WiTu napisał:

To jak już gdzieś w bibliotece trzeba zamienić zmienną

No właśnie o tym mówiłem, może zbyt skrótowo 🙂

A sam się kiedyś na to naciąłem, program który działał przez kilka lat bez problemu na pececie po skompilowaniu na RPi nagle jakoś przestał... okazało się że dla ARM-a GCC domyślnie daje char jako unsigned, a ja potrzebowałęm signed 🙂

 

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Zaraz spróbuje zlokalizować a jak mi się to szybko nie uda tu już użyje dej obrzydliwej metody z wykrywaniem dużych wartości 😛

 

static void lfnPutName(ldir_t *ldir, const char* name, size_t n) {
  unsigned char val;
  size_t k = 13*((ldir->ord & 0X1F) - 1);
  for (uint8_t i = 0; i < 13; i++, k++) {
	val=name[k];
    uint16_t c = val;//k < n ? name[k] : k == n ? 0 : 0XFFFF;
    lfnPutChar(ldir, i, c);
  }
}

Dobra, poprawiłem. name który jest char'em był wrzucany prosto do uint16_t i dlatego był ten problem.

Edytowano przez ElektronPL_WiTu

Udostępnij ten post


Link to post
Share on other sites

SUPER! nie koniec problemów. Tym razem nie chodzi tu nawet to polskie znaki, choć na początku tak myślałem. Jak za pomocą funkcji open tworze plik LFN - na liście plików pokazuje się poprawna nazwa, plik się otwiera wszystko jest ok. (tak jak widać na zrzucie ekranu) Ale gdy włożyłem kartę sd do czytnika to dostałem coś takiego. co teraz zrobić? i co podejrzewać o ten problem...

screen0.png

pc.png

Udostępnij ten post


Link to post
Share on other sites

No niestety - tu już nic nie pomogę, Twoja funkcja nie jest po prostu kompatybilna z oryginalnym vfatem, prawdopodobnie właśnie wymyśliłeś nową nakładkę na FAT:) Musiałbyś:

  1. stworzyć plik o danej nazwie na kompie
  2. podejrzeć (nie wiem gdzie, musiałbyś poszukać gdzie  siedzą długie nazwy w vfat, mógłbym poopowiadać o ext2 i podobnych) jak to wygląda
  3. powtórzyć to samo na Arduino
  4. porównać wyniki

Rozumiem, że poprzez 8.3 pliki się prawidłowo otwieraja na kompie?

 

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Tak wszystko się poprawnie otwiera. Tylko nie wiem co napsułem że zrobił się taki problem. Na oryginalnej bibliotece jest wszystko ok. (oczywiście bez polskich znaków ale) Bo problem dotyczy także plików bez ani jednego polskiego znaku...

Najgorsze że zasadniczo proces modyfikowania tej biblioteki był identyczny jak napisałeś bo robiłem plik z polskimi znakami na kompie a potem sprawdzałem na zegarku jakie wartości daje każdy znak w nazwie. a potem zrobiłem tak aby biblioteka robiła to samo...

 

Edytowano przez ElektronPL_WiTu

Udostępnij ten post


Link to post
Share on other sites
9 minut temu, ElektronPL_WiTu napisał:

robiłem plik z polskimi znakami na kompie a potem sprawdzałem na zegarku jakie wartości daje każdy znak w nazwie

To nie wystarczy - musisz podejrzeć jak wygląda cała struktura na dysku (karcie), prawdopodobnie nie zgadza się jakaś suma kontrolna albo coś w tym rodzaju.

Tu masz opis gdzie to fizycznie siedzi: https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#Directory_table

Udostępnij ten post


Link to post
Share on other sites

Już znalazłem co powoduje ten problem - poprawiona funkcja putName. Gdy wróciłem ją do stanu sprzed modyfikacji jest ok. Tylko znowu nie mogę tworzyć plików z polskimi znakami ale jeszcze nadzieja w wykrywaniu tych ogromnych wartości...

Udostępnij ten post


Link to post
Share on other sites

Chociaż jak tak sobie myślę, to zamienianie tych wartości w jakikolwiek sposób może powodować właśnie takie problemy. Dobrze myślę?

Poza tym jeszcze jedno pytanko bo w putChar  (tak samo jak w getChar)

Jest jakiś if który zapisuje wartość w 3 różne "miejsca"

static void lfnPutChar(ldir_t *ldir, uint8_t i, uint16_t c) {
  //if(c == 65459) c=322;
  if (i < LDIR_NAME1_DIM) {
    ldir->name1[i] = c;
  } else if (i < (LDIR_NAME1_DIM + LDIR_NAME2_DIM)) {
    ldir->name2[i - LDIR_NAME1_DIM] = c;
  } else if (i < (LDIR_NAME1_DIM + LDIR_NAME2_DIM + LDIR_NAME2_DIM)) {
    ldir->name3[i - LDIR_NAME1_DIM - LDIR_NAME2_DIM] = c;
  }
}

Zupełnie nie rozumiem jak to tutaj działa, czemu to tak wygląda?

Udostępnij ten post


Link to post
Share on other sites
33 minuty temu, ElektronPL_WiTu napisał:

Zupełnie nie rozumiem jak to tutaj działa, czemu to tak wygląda?

A zaglądałeś do tego linku który podesłałem?

Pamiętaj, że LFN to wymyślona przez Microsoft proteza na ograniczone nazwy 8.3, długa nazwa jest zapisywana w miejscach, gdzie powinny znajdować się rekordy dotyczące plików, użyto niedozwolonej kombinacji flag aby programy, które nie potrafią operować na długich nazwach nie uznały wpisu za plik czy katalog. A taki rekord ma ograniczoną pojemność, czasem trzeba więcej niż jednego aby zmieścić nazwę. Chłopaki z Microsoftu upchnęli w takim rekordzie 13 znaków w UCS-2 (zresztą porozrzucanych w różnych miejscach), a nazwa może być dłuższa.

Jeśli masz cierpliwość przeanalizuj kod linuksowego drivera vfat, ale stąd już niedaleko do napisania własnej biblioteki FAT obsługującej prawidłowo UTF-8 i/lub UCS-2.

Udostępnij ten post


Link to post
Share on other sites

Szczerze mówiąc wydaje mi się że to będzie za dużo roboty zważywszy, że tworzenie plików z polskimi znakami w tym zegarku jest potrzebne tylko gdy za pomocą aplikacji wysyłam plik z komputera na zegarek i jeśli wyśle plik z polskimi literami to fajnie by było żeby też to tak zapisał. Ale zdecydowanie istotniejsze jest dla mnie, aby zegarek dobrze zapisywał LFN a wystarcza mi to, że poprawnie otwiera pliki i foldery z takimi znakami bo to naprawdę było sporym problemem. Na razie zadowolę się takim rozwiązaniem, że gdy wyśle plik np. "testł.txt" to zegarek zapisze to jako "testl.txt" nie jest to najlepsze rozwiązanie, ale mogę je zaakceptować.

Wielkie dzięki za pomoc, bo myślę, że sam bym sobie nie poradził (choć by dlatego, że myślałem, że wartości po '\' są dziesiętne xD)

I serio mam nadzieję, że to już koniec z tym i jak będę się bawił na różne sposoby zegarkiem to nie odkryje kolejnego poważnego problemu z plikami 😛

Pozdrawiam!

Udostępnij ten post


Link to post
Share on other sites

Tak przeglądam ten wątek, może trochę nieuważnie, ale czy przypadkiem nie jest problem z obsługą znaków dwubajtowych?

Swego czasu drążyłem ten temat w c i do obsługi znaków dwubajtowych rozwiązaniem był typ "wchar_t" służący do definiowania znaków. Dzięki temu było możliwa obsługa strony kodowej UTF8 np. ustawionej w Eclipse. Być może w komunikacji z systemem plików też będzie to dobra wskazówka.

Może taki przykład będzie przydatny:

#include <stddef.h>
 
const wchar_t string[] = L"Ą ś ć ź ń";

Istotny jest ten zapis z dużym "L", a po takiej deklaracji to już bez problemu można było szukać polskich znaków, które dla UTF8 były zdefiniowane tak:

#ifdef UTF_8
const wchar_t utf_8Code[18] = {
	0xC59A,  /*Ś, */
	0xC5B9,  /*Ź, */
	0xC59B,  /*ś, */
	0xC5BA,  /*ź, */
	0xC581,  /*Ł, */
	0xC484,  /*Ą, */
	0xC5BB,  /*Ż, */
	0xC582,  /*ł, */
	0xC485,  /*ą, */
	0xC5BC,  /*ż, */
	0xC486,  /*Ć, */
	0xC498,  /*Ę, */
	0xC583,  /*Ń, */
	0xC393,  /*Ó, */
	0xC487,  /*ć, */
	0xC499,  /*ę, */
	0xC584,  /*ń, */
	0xC3B3,  /*ó, */
};
#endif

 

Udostępnij ten post


Link to post
Share on other sites
5 godzin temu, Zealota napisał:

czy przypadkiem nie jest problem z obsługą znaków dwubajtowych?

Nie - to wina uproszczenia biblioteki. W przypadku FAT wszystkie znaki są dwubajtowe, tyle że biblioteka posługuje się wszędzie typem char a nie wchar_t a konwersja po prostu albo ucina starsze bity, albo wstawia tam zera.

Natomiast to co napisałeś to jakieś dziwne dziwactwo - przecież wchar_t (czyli UCS-2 albo UTF-32) nie ma nic wspólnego z UTF-8, a nie bardzo rozumiem w jaki sposób chcesz kody UTF-8 (które akurat w przypadku polskich literek stanowią ciągi dwóch znaków ale w przypadku innych alfabetów już nie) wpisywać do typu, który z założenia może mieć różną szerokość (np. dla Linuksa wchar_t ma 32 bity, ale dla Windows 16). Możesz to jakoś przybliżyć?

 

Udostępnij ten post


Link to post
Share on other sites
10 godzin temu, ethanak napisał:

Natomiast to co napisałeś to jakieś dziwne dziwactwo - przecież wchar_t (czyli UCS-2 albo UTF-32) nie ma nic wspólnego z UTF-8, a nie bardzo rozumiem w jaki sposób chcesz kody UTF-8 (które akurat w przypadku polskich literek stanowią ciągi dwóch znaków ale w przypadku innych alfabetów już nie) wpisywać do typu, który z założenia może mieć różną szerokość (np. dla Linuksa wchar_t ma 32 bity, ale dla Windows 16). Możesz to jakoś przybliżyć?

Przytoczę zatem ze swojego podwórka pewien przypadek. Zwykle do programowania używam Eclipse zarówno pod Linuxem jak i Windows i czasami  muszę dokonywać importu projektów z jednego środowiska do drugiego i na odwrót. Żeby w plikach źródłowych, które korzystają z polskich znaków nie mieć kłopotu z krzaczkami to założyłem sobie, żeby strony kodowe mieć w obu środowiskach ustawione na UTF8 - założyłem sobie, że tak będzie również dobrze pod kątem przyszłych projektów, które np. będą musiały komunikować się między sobą i poprawnie działać z polskimi znakami i tak zostało.

Jeśli więc w plikach źródłowych pojawiają się polskie znaki, np. napisy w pamięci flash, czy komentarze po polsku, to żeby kod był "czysty i poprawny i widoczny" musiałem skorzystać z "czegoś" - prawdopodobnie bez dobrego rozeznania, padło właśnie na wchar_t, użycie char nie wystarczyło. Kawałek kodu, który przytoczyłem, szczególnie w dziedzinie definicji napisów w pamięci, w różnych stronach kodowych się sprawdza - na pewno pod Windows - w Linuksie jeszcze nie testowałem. Mogę ustawić choćby na UNICODE i skorzystać z innych wzorców znaków i również poprawnie to działa.

Tłumaczę sobie to tak, że przy ustawionej stronie kodowej UTF8 znaku nie da się "upakować" do jednobajtowego char 🙂. Pod Linuksem też chyba się "zmieści" skoro wchar_t ma 4 bajty. Oczywiście to powoduje marnowanie pamięci, ale chyba bez przesady....

Gdybym wcześniej zdecydował się na stronę kodową CP1250, to nie byłoby tego problemu, ale pewnie niepotrzebnie pojawiły się ograniczenia "gdzie indziej".

Jeśli jest lepsze rozwiązanie niż skorzystanie z wchar_t  ze strona kodowa UTF8, to z chęcią je poznam.

 

Udostępnij ten post


Link to post
Share on other sites
40 minut temu, Zealota napisał:

użycie char nie wystarczyło.

A dlaczego chcesz mieszać wchar_t z UTF-8? UTF-8 przechowuje napisy w jednobajtowych ciągach o różnej długości (od jednego do 6), wchar_t natomiast to zmienne typu uint o rozmiarze większym niż bajt. W razie konieczności konwersja utf-8 - wchar_t jest robiona zupełnie inaczej (tak jak to w którymś poście pokazał kolega wątkotwórca) a nie poprzez bezmyślne wtykanie do wchar_t ciągu bajtów (zresztą niezależnie od systemu - sześciu bajtów i tak tam nie wrzucisz).

Mówisz że Twoje rozwiązania zadziała pod Linuxem? Spróbuj to skompilować np. na Amidze (pod Linuxem oczywiście), możesz się lekko zdziwić 😉 Spróbuj zgadnąć dlaczego, a jeśli nie zgadniesz to zapoznaj się z pojęciem "endianness".

 

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...