UNIX vs Windows filer - Checksum olika.. (Java)

Permalänk
Medlem

UNIX vs Windows filer - Checksum olika.. (Java)

Hej,

Jag har ett litet problem. Det är nämligen så att jag har en application (Java) som laddar ner filer från en dropzone för att sedan kontrollera om dess checksum överensstämmer med den checksum som återfinns i filnamnet.

Nu till problemet: Dessa filer, efter att jag kopierat dem lokalt är UNIX filer och man återfår inte samma checksum-värde ur dessa som om jag manuellt konverterar dem till Windowsfiler. Hur bär jag mig åt för att konvertera dem till Windowsfiler med java?

Alltså: Hur konverterar man en UNIX fil till Windows med Java?

Tack

Visa signatur

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." - Brian W. Kernighan

Permalänk
Medlem

Hm.. vad är det för skillnad på en "Windowsfil" och en "UNIX-fil" ? Källkodsfiler går att kompilera oberoende av plattform etc.
Menar du kanske att du vill byta radbytestecken..?

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem

Windows och DOS radbryter textfiler med hex 0D, 0A medan textfiler i UNIX bara har ett 0A där, kan vara ditt problem. Det kan ju också vara olika teckenuppsättning som ställer till det.
Men om du räknar checksumma över hela filen borde det inte spela någon roll.

Visa signatur

ii7 2600K @ 4500 mhz, P8Z68-V Pro, 16 GB Vengeance LP @ 1600 mhz, Samsung 830 256 GB (system), X25-M 160 GB, Chieftec 650W PSU, GTX 660 2GB, CM ATCS 840, NH-D14, WIN 8 pro. Sidekick - Acer TimelineX 3820TG.

Permalänk
Medlem
Skrivet av sorkin:

Men om du räknar checksumma över hela filen borde det inte spela någon roll.

Det borde det visst?

Permalänk
Medlem
Skrivet av You:

Det borde det visst?

Hur då? Är aningen oinsatt, trodde att en hashsumma togs fram från en fils binära innehåll.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

Hur då? Är aningen oinsatt, trodde att en hashsumma togs fram från en fils binära innehåll.

Det är vad jag menar också såvida man inte gör någon form av konvertering vid överföringen.

Visa signatur

ii7 2600K @ 4500 mhz, P8Z68-V Pro, 16 GB Vengeance LP @ 1600 mhz, Samsung 830 256 GB (system), X25-M 160 GB, Chieftec 650W PSU, GTX 660 2GB, CM ATCS 840, NH-D14, WIN 8 pro. Sidekick - Acer TimelineX 3820TG.

Permalänk
Medlem
Skrivet av Teknocide:

Hur då? Är aningen oinsatt, trodde att en hashsumma togs fram från en fils binära innehåll.

Precis. Alltså spelar det koll vilka radbrytningar och vilken teckenkodning man använder.

Permalänk
Medlem

Tack för era spekulationer, men någon som har svaret på frågan: Hur konverterar man en fil från UNIX till DOS med hjälp av Java?

Visa signatur

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." - Brian W. Kernighan

Permalänk
Medlem
Skrivet av ePoint:

Tack för era spekulationer, men någon som har svaret på frågan: Hur konverterar man en fil från UNIX till DOS med hjälp av Java?

Det kan vi bara svara på om du talar om vad det är för fil du pratar om, finns ingen generell skillnad mellan "filer" i UNIX och DOS.

Visa signatur

ii7 2600K @ 4500 mhz, P8Z68-V Pro, 16 GB Vengeance LP @ 1600 mhz, Samsung 830 256 GB (system), X25-M 160 GB, Chieftec 650W PSU, GTX 660 2GB, CM ATCS 840, NH-D14, WIN 8 pro. Sidekick - Acer TimelineX 3820TG.

Permalänk

Om man bara kopierar filerna mellan systemen borde de vara identiska (gissning, jag vet inte detta med säkerhet, men har svårt att tänka mig något annat). Om det är det du gör så måste det vara checksummeberäkningen som skiljer sig (jag antar alltså att du kollar checksumman i unix och får checksumma x och när du kollar i windows får du checksumma y). Hur kontrollerar du checksumman?

Permalänk
Medlem
Skrivet av ePoint:

Tack för era spekulationer, men någon som har svaret på frågan: Hur konverterar man en fil från UNIX till DOS med hjälp av Java?

Man kan inte göra mycket annat än spekulera då du gett en så otydlig problembeskrivning. Rör det sig om text eller binära filer? Om det är text kan du inte förvänta dig att få samma checksum efter en radbrytningskonvertering; kontrollera checksum innan.

För att konvertera text till UNIX-standard ersätter du alla \r\n med \n.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem

det beror nog på hur filöverföringen görs. behandlas filerna som en byteström så ska filerna vara identiska i båda ändar, men om java programmet behandlar det som text och sedan sparar själv så blir det olika radbrytningar som flera påpekat och hashen kommer att skilja sig.

som sagt det finns inget "dos-fil" eller "unix-fil". skiljer sig hashen så kan till exempel något av följande vara anledningen:

1) nedladdningen gick dåligt
2) javaprogrammet dabbar med din fil och sparar den annorlunda
3) javaprogrammet använder fel hashalgoritm
4) ... ?

Permalänk
Medlem

Jag löste det genom att kopiera filen till en ny fil först på följande sätt.

Jag läser varje rad och sätter in den i den nya filen följt av "\r\n" som jag läste mig till att det såg ut i en DOS-fil jämfört mot "\n" i en UNIX-fil.

Nu fungerar det klockrent. Tack för tankar och diskussion.

Visa signatur

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." - Brian W. Kernighan

Permalänk

Det är ju helt åt helvete att du i ett program som tankar ner filer ska behöva loopa igenom varje rad istället för att kunna hantera det som en byteström.

Det här drar ner prestandan något enormt mycket och är helt FEL lösning på ditt problem.

Hantera det som en byteström istället så kommer det att bli samma innehåll på hos dig som på servern iaf.

Permalänk
Medlem
Skrivet av adisbladis:

Det är ju helt åt helvete att du i ett program som tankar ner filer ska behöva loopa igenom varje rad istället för att kunna hantera det som en byteström.

Det här drar ner prestandan något enormt mycket och är helt FEL lösning på ditt problem.

Hantera det som en byteström istället så kommer det att bli samma innehåll på hos dig som på servern iaf.

Det lustiga är ju att för att ladda ner filen använder jag en byteström.

public InputStream load( String filename ) { try { SftpProgressMonitor monitor = new MyProgressMonitor(); ByteArrayOutputStream out = new ByteArrayOutputStream(); c.get( filename, out, monitor ); return new ByteArrayInputStream( out.toByteArray() ); } catch( Exception e ){ print( e.toString() ); } return null; }

is = load(fileName); fos = new FileOutputStream(tempFile); bis = new BufferedInputStream(is); bos = new BufferedOutputStream(fos); int i; while ((i = bis.read()) != -1) { bos.write(i); }

Är detta inte att ladda ner den med en byteström?

Det är i det här läget jag måste göra kopieringen för att den inte längre ska vara en UNIX fil.

Visa signatur

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." - Brian W. Kernighan

Permalänk
Medlem

Jag slängde ihop följande testprogram:

package main; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.URL; import java.net.URLConnection; public class DownloadFile { public static void main(String[] args) { URL url = DownloadFile.class.getResource("/textfilesources/unix-ascii.txt"); DownloadFile.runTest(url, true, "unix-ascii-preserve.txt"); DownloadFile.runTest(url, false, "unix-ascii-dont-preserve.txt"); url = DownloadFile.class.getResource("/textfilesources/unix-utf8.txt"); DownloadFile.runTest(url, true, "unix-utf8-preserve.txt"); DownloadFile.runTest(url, false, "unix-utf8-dont-preserve.txt"); url = DownloadFile.class.getResource("/textfilesources/dos-ascii.txt"); DownloadFile.runTest(url, true, "dos-ascii-preserve.txt"); url = DownloadFile.class.getResource("/textfilesources/dos-utf8.txt"); DownloadFile.runTest(url, true, "dos-utf8-preserve.txt"); } public static void runTest(URL url, boolean preserveLinebreaks, String outFilename) { try { DownloadFile.downloadFile(url, preserveLinebreaks, outFilename); } catch (IOException e) { System.err.println("IOException: " + e.getMessage()); } } public static void downloadFile(URL url, boolean preserveLinebreaks, String outFilename) throws IOException { FileOutputStream fos = new FileOutputStream(outFilename); URLConnection urlConnection = url.openConnection(); InputStream is = urlConnection.getInputStream(); if (preserveLinebreaks) { DataInputStream dis = new DataInputStream(is); int bytesAvailable = dis.available(); byte[] allBytes = new byte[bytesAvailable]; dis.readFully(allBytes); dis.close(); fos.write(allBytes); fos.flush(); fos.close(); } else { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); OutputStreamWriter osw = new OutputStreamWriter(fos); String line = null; final String lineSeparator = System.getProperty("line.separator"); while ((line = reader.readLine()) != null) { osw.write(line + lineSeparator); } osw.flush(); osw.close(); } } }

Det är inte production quailty code och har säkert flera brister, men det verkar fungera i mina tester, kanske är det till nån hjälp.
Jag gjorde fyra testfiler: UNIX-ASCII, UNIX-U8, DOS-ASCII, DOS-U8 som jag laddar ned. Vad man vill få till här är att encodingen bibehålls och man ska kunna välja att behålla ursprungsfilens line break style eller inte. I ditt fall då du ska jämföra checksums vill du ju ha kvar ursprungsfilens encoding och line break style.
Jag har sex testfall:
Ladda ned alla filer med bibehållen encoding och line break style - funkar.
Ladda ned unix-filerna och gör om till dos line breaks men behåll encoding - funkar.

Jag har gjort testerna under windows och jag har använt ultraedit för att skapa sourcefilerna och inspektera outputfilerna.

Edit 1: fixade en liten detalj i koden