文件md5散列更改时(对于netty传输)(File md5 hash changes when chunking it (for netty transfer))
底部的问题
我使用netty将文件传输到另一台服务器。 由于WebSocket协议,我将文件块限制为1024 * 64字节(64KB)。 以下方法是本地示例文件会发生什么情况:
public static void rechunck(File file1, File file2) { FileInputStream is = null; FileOutputStream os = null; try { byte[] buf = new byte[1024*64]; is = new FileInputStream(file1); os = new FileOutputStream(file2); while(is.read(buf) > 0) { os.write(buf); } } catch (IOException e) { Controller.handleException(Thread.currentThread(), e); } finally { try { if(is != null && os != null) { is.close(); os.close(); } } catch (IOException e) { Controller.handleException(Thread.currentThread(), e); } } }
该文件由
InputStream
加载到ByteBuffer中,并直接写入OutputStream
。 该过程中文件的内容不能改变。为了获得文件的
md5-hashes
,我编写了以下方法:public static String checksum(File file) { InputStream is = null; try { is = new FileInputStream(file); MessageDigest digest = MessageDigest.getInstance("MD5"); byte[] buffer = new byte[8192]; int read = 0; while((read = is.read(buffer)) > 0) { digest.update(buffer, 0, read); } return new BigInteger(1, digest.digest()).toString(16); } catch(IOException | NoSuchAlgorithmException e) { Controller.handleException(Thread.currentThread(), e); } finally { try { is.close(); } catch(IOException e) { Controller.handleException(Thread.currentThread(), e); } } return null; }
所以:理论上它应该返回相同的散列,不是吗? 问题是它返回两个不同的散列,每次运行都没有区别。文件大小保持不变,内容也是一样。 当我
in: file-1
,out: file-2
以及in: file-2
和out: file-3
运行一次方法时,in: file-2
和out: file-3
的哈希值是相同的! 这意味着该方法将每次以相同的方式正确更改文件。1. 58a4a9fbe349a9e0af172f9cf3e6050a 2. 7b3f343fa1b8c4e1160add4c48322373 3. 7b3f343fa1b8c4e1160add4c48322373
这是一个比较所有缓冲区的小测试,如果它们是相同的。 测试是积极的。 所以没有任何分歧。
File file1 = new File("controller/templates/Example.zip"); File file2 = new File("controller/templates2/Example.zip"); try { byte[] buf1 = new byte[1024*64]; byte[] buf2 = new byte[1024*64]; FileInputStream is1 = new FileInputStream(file1); FileInputStream is2 = new FileInputStream(file2); boolean run = true; while(run) { int read1 = is1.read(buf1), read2 = is2.read(buf2); String result1 = Arrays.toString(buf1), result2 = Arrays.toString(buf2); boolean test = result1.equals(result2); System.out.println("1: " + result1); System.out.println("2: " + result2); System.out.println("--- TEST RESULT: " + test + " ----------------------------------------------------"); if(!(read1 > 0 && read2 > 0) || !test) run = false; } } catch (IOException e) { e.printStackTrace(); }
问题: 你能帮我在不更改散列的情况下分块文件吗?
Question at the bottom
I'm using netty to transfer a file to another server. I limit my file-chunks to 1024*64 bytes (64KB) because of the WebSocket protocol. The following method is a local example what will happen to the file:
public static void rechunck(File file1, File file2) { FileInputStream is = null; FileOutputStream os = null; try { byte[] buf = new byte[1024*64]; is = new FileInputStream(file1); os = new FileOutputStream(file2); while(is.read(buf) > 0) { os.write(buf); } } catch (IOException e) { Controller.handleException(Thread.currentThread(), e); } finally { try { if(is != null && os != null) { is.close(); os.close(); } } catch (IOException e) { Controller.handleException(Thread.currentThread(), e); } } }
The file is loaded by the
InputStream
into a ByteBuffer and directly written to theOutputStream
. The content of the file cannot change while this process.To get the
md5-hashes
of the file I've wrote the following method:public static String checksum(File file) { InputStream is = null; try { is = new FileInputStream(file); MessageDigest digest = MessageDigest.getInstance("MD5"); byte[] buffer = new byte[8192]; int read = 0; while((read = is.read(buffer)) > 0) { digest.update(buffer, 0, read); } return new BigInteger(1, digest.digest()).toString(16); } catch(IOException | NoSuchAlgorithmException e) { Controller.handleException(Thread.currentThread(), e); } finally { try { is.close(); } catch(IOException e) { Controller.handleException(Thread.currentThread(), e); } } return null; }
So: just in theory it should return the same hash, shouldn't it? The problem is that it returns two different hashes that do not differ with every run.. file size stays the same and the content either. When I run the method once for
in: file-1
,out: file-2
and again within: file-2
andout: file-3
the hashes of file-2 and file-3 are the same! This means the method will properly change the file every time the same way.1. 58a4a9fbe349a9e0af172f9cf3e6050a 2. 7b3f343fa1b8c4e1160add4c48322373 3. 7b3f343fa1b8c4e1160add4c48322373
Here is a little test that compares all buffers if they are equivalent. Test is positive. So there aren't any differences.
File file1 = new File("controller/templates/Example.zip"); File file2 = new File("controller/templates2/Example.zip"); try { byte[] buf1 = new byte[1024*64]; byte[] buf2 = new byte[1024*64]; FileInputStream is1 = new FileInputStream(file1); FileInputStream is2 = new FileInputStream(file2); boolean run = true; while(run) { int read1 = is1.read(buf1), read2 = is2.read(buf2); String result1 = Arrays.toString(buf1), result2 = Arrays.toString(buf2); boolean test = result1.equals(result2); System.out.println("1: " + result1); System.out.println("2: " + result2); System.out.println("--- TEST RESULT: " + test + " ----------------------------------------------------"); if(!(read1 > 0 && read2 > 0) || !test) run = false; } } catch (IOException e) { e.printStackTrace(); }
Question: Can you help me chunking the file without changing the hash?
原文:https://stackoverflow.com/questions/49588868
相关问答
更多-
Log4j 配置与使用 java.sql[2022-07-30]
你这个打印的是error级别的,你把error换成debug再试试 -
这是正确的,最初ResultSet的游标指向第一行之前,如果第一个调用next()返回false则ResultSet没有数据。 如果您使用此方法,则可能必须立即调用beforeFirst()来重置它,因为它已经将自己定位在第一行之后。 然而,应该注意的是, Seifer的答案是对这个问题的更为优雅的解决方案。 That's correct, initially the ResultSet's cursor is pointing to before the first row, if the first c ...
-
coldfusion.sql.QueryTable实现了javax.sql.RowSet,它扩展了java.sql.ResultSet 因此,正如你发现的那样,你不需要做任何事情。 ColdFusion查询已经是Java ResultSet。 coldfusion.sql.QueryTable implements javax.sql.RowSet, which extends java.sql.ResultSet Thus, as you discovered, you don't need to do ...
-
基本上您将光标定位在第一行之前,然后请求数据。 您需要将光标移动到第一行。 result.next(); String foundType = result.getString(1); 在if语句或循环中这样做是很常见的。 if(result.next()){ foundType = result.getString(1); } Basically you are positioning the cursor before the first row and then requesting d ...
-
java.sql.Timestamp扩展java.util.Date 。 你想要这样的东西: String S = new SimpleDateFormat("MM/dd/yyyy").format(myTimestamp); 包括时间: String S = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(myTimestamp); java.sql.Timestamp extends java.util.Date. You can do: Str ...
-
DarkSquirrel42是对的 - 您无法使用?替换select列列表? 参数标记。 相反,您也可以将String.format格式化为例如。 坏: *select ? from INVENTORY_TABLE_NAME where SKU = ? 好: select QUANTITY_IN_STOCK from INVENTORY_TABLE_NAME where SKU = ? DarkSquirrel42 is right -- you can't replace the column lis ...
-
你不应该重用一个Statement。 创建新查询时,需要使用新的Statement对象。 替换rs1 = stmt.executeQuery("SELECT ASK FROM '" + title + "' ;"); rs1=c.createStatement().executeQuery("SELECT ASK FROM '" + title + "' ;"); you should not reuse a Statement. When you create a new Query, you need ...
-
你需要自己处理ResultSet对象rs 。 while(rs.next()){ String ign = rs.getString("IGN"); // ... get uuid and admin level System.out.println(ign + uuid ...); } 如果您不知道列名称,请使用ResultSet#getMetaData() : ResultSetMetaData rsmd = rs.getMetaData(); int columnCount = rsmd ...
-
是否可以直接从Groovy返回java.sql.ResultSet?(Is it possible to directly return the java.sql.ResultSet from Groovy?)[2024-01-03]
不是真的。 使用Groovy的Sql主要原因之一是自动处理资源(这就是为什么有些方法使用闭包与ResultSet进行交互,但是没有返回它的方法 - 以确保它们被关闭)。 我强烈建议您重新考虑为什么要传递对ResultSet引用(可以保留服务器资源),而不是使用表示这些结果的POJO / POGO。 但是,如果您坚持使用ResultSet ,并且只需要很少的便捷方法,我想一个选项就是将这些方法复制到您的代码库中。 正如您从源代码中看到的那样, Sql是一个比普通旧JDBC更薄的包装器。 但是,就你所听到的情况 ... -
据我所知,ResultSet不“包含”数据。 如果您调用http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html#next(),ResultSet将从与数据库的基础(JDBC)连接获取数据。 如果ResultSet是序列化并传输到另一台计算机,则这是不可能的。 那里的连接将无法使用。 As far as I know the ResultSet does not "contain" the data. If you call http: ...