4

就像瓷砖说的那样,我的 Java 应用程序不能正常工作,因为它在 Eclipse 上开发时工作正常。

我完成了在 Eclipse 上构建和测试我的应用程序。正如我所料,它工作得很好。我需要将它部署为一个可运行的 jar,这样我的客户就不能在他们的系统上使用它。我通过在 Eclipse 上导出它使其成为一个可运行的 jar。当我运行可运行 jar 时,应用程序开始正常工作一段时间并停止读取文件。我在 Eclipse 上的相同代码上没有任何问题。

似乎不起作用的源代码片段如下。

            sfis = new SmbFileInputStream(sFile);
            in = new BufferedInputStream(sfis);

            byte buf[] = new byte[(int)sFile.length()];
            int pos = 0;
            int size = 10;
            int temp;

            while((size=in.read(buf, pos, size)) > 0){
                pos += size; 
                temp = buf.length - pos;
                if(temp < 10){
                    size = temp;
                }
            }

在 Eclipse 上它不会引起任何问题。它完美地从 SMB 连接读取数据并完成其工作。但是从 jar 应用程序来看,它似乎在某个时候停止从 while 循环内的输入流中读取。这是一个我从未经历过的非常奇怪的案例。我找不到任何解决方案。

这是因为我的代码或 Eclipse 可能错误制作的 jar 文件吗?

- - - - - 附加信息 - - - - - - - - - -

在 Edmondo1984 的大力帮助下,我找到了 jar 程序停止的地方。当它从 SmbFile 进入 inputstream 时,会创建一个新线程 jcifs.util.transport.Transport,该线程被简单地阻塞,应用程序创建另一个 jcifs.util.transport.Transport,依此类推。创建 8 个或 9 个 jcifs.util.transport.Transport 线程后,它被卡住了,什么也不做。

相同的代码,相同的 jcifs 库。但是在 Eclipse 上运行和在本地机器上作为可运行 jar 运行时的工作方式不同。我不知道为什么会这样。

4

3 回答 3

2

“流中没有更多内容”的返回值是-1(参见Javadoc)。

想象一下,如果您尝试in.read(buf, pos, size)但底层证券仍然不可用,会发生什么。然后调用立即返回0(零)返回值。这样,循环条件评估为假并退出循环。所以我认为你应该比较!= -1.

另一个可能的问题:您还可以考虑如果size = 0(例如由于上述情况)和temp >= 10. size因为您直接将to的值反馈in.read(buf, pos, size)为要读取的最大字节数,所以假设您已经更正了与 的比较,您可能会陷入无限循环!= -1

于 2012-07-19T09:48:28.860 回答
1

在干预流时,这种行为很常见。小的算法错误可能会在不同的环境中导致不同的症状。

您可以将“调试”信息打印到控制台,以更好地了解代码停止的位置和原因。我很确定它在读取方法上。

您的代码有几处问题,最臭名昭著的是块:

temp = buf.length - pos;
if(temp < 10){
  size = temp;
}

为什么?当剩下 10 个或更少字节时,您将尝试在下一次 read() 中读取它们,否则您可能会尝试读取太多(再次读取整个文件大小)。在 Eclipse 中运行,该文件可能是在第一次 read() 中读取的,而在 Eclipse 中显然不是。尝试将您的代码更改为以下内容:

FileInputStream sfis = new FileInputStream(sFile);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte buf[] = new byte[4096];
int read = sfis.read(buf);
while(read>0){
  baos.write(buf, 0, read);
  read = sfis.read(buf);
}
sfis.close();

还要考虑使用Apache 的 Java IO 实用程序代码,而不是总是编写这种类型的代码。Java 中的 IO 需要大量样板文件,而优秀的程序员有更好的事情要做。

附带说明:将文件读入内存通常是个坏主意。除非您打算以某种方式将其数据作为一个整体进行转换,否则流式传输总是更好。我不知道您的程序是做什么用的,但请记住这一点:如果您尝试读取 10GB 文件会发生什么?还是几个?

快乐编码,

于 2012-07-19T10:37:35.570 回答
0

Java 在任何方面都对大写字母敏感。例如,如果您有名为 image.PNG 的文件,并且在代码中将位置设置为“/image.png”(而不是“/image.PNG”),它将在 eclipse 中正常工作,但在导出可运行的 jar 文件后,java VM 会无法找到该文件。

于 2016-04-11T08:28:44.367 回答