Wczytuję plik xml poleceniem LoadFromFile, ale na końcu pliku dokleja pustą linię . Jak mogę ją wykasować? Potrzebuję plik identyczny. Jak pod debagerem podglądam ten plik to widzę na końcu ostatniego wiersza '#$D#$A'. Jeżeli wysyłam taki plik na bramkę e-deklaracje, to mam informację, że plik "z niepoprawnym podpisem". Plik różni się właśnie pustą linią na końcu.
Jestem jeszcze swieży w temacie.
Moze pokaz coś więcej np kawalek kodu.
KsefIntegrator napisał(a):
Moze pokaz coś więcej np kawalek kodu.
wygląda to tak:
lstXML.LoadFromFile(FileNameToSend,TEncoding.UTF8);
s := lstXML.GetText;
sd.document := s ;
do zmiennej s wczytuje mi to (jest to część tego pliku, chodzi mi o ostatni wers). Na końcu ostatniego wiersza dokleja #$D#$A
czyli pustą linie
<PozycjeSzczegolowe>'#$D#$A' <P_11>1</P_11>'#$D#$A' <P_28>1</P_28>'#$D#$A' <P_29>30879.47</P_29>'#$D#$A' <P_30>2250.00</P_30>'#$D#$A' <P_31>28629.47</P_31>'#$D#$A'
<P_33>243</P_33>'#$D#$A' <P_95>4174.46</P_95>'#$D#$A' <P_121>2</P_121>'#$D#$A' <P_122>2403.47</P_122>'#$D#$A' </PozycjeSzczegolowe>'#$D#$A'
<Pouczenie>1</Pouczenie>'#$D#$A'</Deklaracja></ds:Object></ds:Signature>'#$D#$A
poleceniem wyrzucam ostanie znaki:
s:= StringReplace(lstXML.GetText,'</Deklaracja></ds:Object></ds:Signature>'#$D#$A,('</Deklaracja></ds:Object></ds:Signature>'),[rfReplaceAll]) ;
teoretycznie polecenie StringReplace
działa, ale finalnie mam błąd.
Pozdrawiam
słuchaj, a skąd u ciebie w pliku te entery i znaki nowej linii co chwilę? Przecież tego nie ma w pliku xml?
czym jest lstXML
i sd
?
abrakadaber napisał(a):
czym jest
lstXML
isd
?
lstXML:=TstringList.Create;
sd zmienna pomocnicza.
Interesuje mnie zmienna s
Plik xml wczytuję w Delphi. Chce wysłac podpisany plik Xml moją aplikacją ( podpisany przez zewnętrzny program CERTUM) .
Koniec każdego wiersza z pliku xml w Delphi wyświetla właśnie kodem szesnastkowym w postaci #$D#$A
(#$D
znak końca linii i #$A
nowej linii) .
Ostatni wiersz kończący plik
<Pouczenie>1</Pouczenie>'#$D#$A'</Deklaracja></ds:Object></ds:Signature>'#$D#$A
też ma znak '#$D#$A
nie mogę się tego pozbyć, a to powoduje, że plik różni się od oryginału i mam bład '403 Dokument niepoprawny z podpisem'
To chyba nie pomoże ale w takich przypadkach zamiast stosować dziwolągi typu:
s:= StringReplace(lstXML.GetText,'</Deklaracja></ds:Object></ds:Signature>'#$D#$A,('</Deklaracja></ds:Object></ds:Signature>'),[rfReplaceAll]) ;
po prostu użyj funkcji Trim
w tym wypadku nawet TrimRight
.
Jak mowa o podpisie - podpisany jest blok bajtów *)
- unikałbym jak diabeł święconej wody - interfejsów znakowych / liniowych
Tu trochę gra maniera Delphi, że ZAWSZE się programista wybierze w implemenatcji "to co widac", czyli np TStringList (choć w Delphi można wybrać jeszcze gorzej: użyć jako kontenera danych komponentu GUI)
Jako programista Javy / C# był wyłącznie używał odczytu i wysyłki byte[]
W interfejsach znakowych zawsze czają się potwory (cytat za sąsiednim wątkiem), nawet jak nie fałszywe EOLN, to niejawne konwersje kdowoania
*)
Hipotetycznie wyobrażam sobie, teoria tego nie wyklucza, podpisu wobec kolekcji linii czy innymi zdefiniowanymi formatami znakowymi, ale nie spotkałem w praktyce. W praktyce podpisywany jest byte[]
to nawet nie chodzi o to, że to Delphi - w każdym języku można klepać ciulaty kod.
Do wczytywania/operacji na plikach służy TStream
, w szczególności TFileStream
i program do obsługi plików powinno się pisać tak, żeby NIE KORZYSTAĆ ze stringów (o ile nie ma potrzeby go wyświetlić, a nawet wtedy powinno się go przekonwertować z formatu binarnego na tekst)
BTW to napisz jeszcze co to jest sd
a najlepiej by było jakbyś dał CAŁY kod do wysyłania a nie jakiś magiczny wycinek
Kacer_2 napisał(a):
Wczytuję plik xml poleceniem LoadFromFile, ale na końcu pliku dokleja pustą linię . Jak mogę ją wykasować?
Otworzyć plik, sprawdzić czy jest $0A0D
na końcu, jeśli jest to zmienić rozmiar strumienia, zamknąć plik. ;)
uses
Classes;
var
FileStream: TFileStream;
begin
FileStream := TFileStream.Create('file.xml', fmOpenReadWrite);
try
if FileStream.Size >= 2 then
begin
FileStream.Position := FileStream.Size - 2;
if FileStream.ReadWord() = Word($0A0D) then
FileStream.Size := FileStream.Size - 2;
end;
finally
FileStream.Free();
end;
end.
To przykład z Free Pascala, przetestowany i działa poprawnie — powinien być kompatybilny z Delphi. Możesz sobie napisać do tego osobną funkcję, jeśli zawartość tego pliku masz np. w strumieniu innego rodzaju. W każdym razie jeśli masz strumień, to możesz po prostu zmienić jego rozmiar na mniejszy o dwa bajty.
Chciałem najpierw sprawdzić dokumentację Delphi, aby się upewnić, że w nim też tak się da, ale ich strona leży i kwiczy.
abrakadaber napisał(a):
to nawet nie chodzi o to, że to Delphi - w każdym języku można klepać ciulaty kod.
Ale w borlandach jest szczególna fizyka czasoprzestzreni /inna prędkość światła itd
Konstrukty i struktury danych, które nigdy nie są użyte przez wizarda (oraz nie mają reprezentacji na tooboxie), są nieistniejące. Jak człowiek bez konta na fejsie, nie żyje. Albo kobiety 50+, które mówią, że na ulicy są niewidzialne
Co ze szczególną złośliwością podkreślę, istnieje zupełnie szeroki zestaw np kontenerów w bliobliotece standardowej, i na owe czasy najbardziej fantastyczny Help, wielkie źródło sukcesu tego środowiska w polskim rynku pirackim.
abrakadaber napisał(a):
i program do obsługi plików powinno się pisać tak, żeby NIE KORZYSTAĆ ze stringów (o ile nie ma potrzeby go wyświetlić, a nawet wtedy powinno się go przekonwertować z formatu binarnego na tekst)
200% na tak
Jeżeli chodzi o same dokumenty XML z użyciem TStriingList
do jego wczytania nie byłoby problemu, bo przecież to są pliki tekstowe gdyby nie to że te pliki mogą zawierać BOM a on jeżeli się użyje do tego kodowania TEncoding.UTF8
automatycznie zostanie pominięty (TEncoding.ANSI
go zostawi ale popsuje kodowanie innych specyficznych znaków w tym polskich liter) więc jeżeli plik faktycznie zawiera BOM to będzie problem. a nie przetwarzanie znaków #13#10
choć niepotrzebnie dodane na końcu też nie mogą zostać.
Krótko mówiąc jeżeli to faktycznie problem z BOM to jeżeli jest potrzeba operowania na wczytanym pliku (nie wiem po co traktując go jako string a nie TXMLDocument
) trzeba użyć TStringStream
, bo ma metodę DataString
a nic nie popsuje w przypadku danych tekstowych albo jeżeli nie ma takiej potrzeby TFileStream
.