使用Java将文件从FTP下载到本地会使文件无法读取-编码问题

使用Java将文件从FTP下载到本地会使文件无法读取-编码问题,java,hadoop,ftp,elastic-map-reduce,amazon-emr,Java,Hadoop,Ftp,Elastic Map Reduce,Amazon Emr,我开发了一个代码,可以从FTP读取非常大的文件,并使用Java将其写入本地机器。执行此操作的代码如下所示。这是CustomInputFormat if(!processed) { System.out.println("in processed"); in = fs.open(file); processed=true; } while(bytesR

我开发了一个代码,可以从FTP读取非常大的文件,并使用Java将其写入本地机器。执行此操作的代码如下所示。这是
CustomInputFormat

 if(!processed)
            {
                            System.out.println("in processed");
                in = fs.open(file);
    processed=true; 
            }
while(bytesRead <= fileSize) {

                 byte buf[] = new byte[1024]; 

                try {
                    in.read(buf);
                    in.skip(1024);
                    bytesRead+=1024;
                    long diff = fileSize-bytesRead;
                    if(diff<1024)
                    {
                        break;
                    }
        value.set(buf, 0, 1024); // This is where the value of the record is set and it goes to the mapper . 
                } 
                catch(Exception e)
                {
                    e.printStackTrace();
                }

            }
            if(diff<1024)
            {
                int difference= (int) (fileSize-bytesRead);

                 byte buf[] = new byte[difference]; 
                in.read(buf);
                bytesRead+=difference;
            }

                    System.out.println("closing stream");
                    in.close();
这个问题:我相信与我的有关,但我无法理解


有什么建议吗

我发现你的代码有很多问题。读取整个文件是一种奇怪的方式。 例如:

in.read(buf);
in.skip(1024);
bytesRead+=1024;
错误,
in.read(buf)
返回读取的字节数,并将流位置设置为当前位置old position+n read bytes。因此,您不需要跳过——这是一个错误,因为read已经定位了流

验证文件的校验和以确保它们是相同的。(使用md5或其他东西) 我很确定校验和和和文件大小都不一样


您应该使用来进行文件处理。否则请看。

我发现您的代码存在许多问题。读取整个文件是一种奇怪的方式。 例如:

in.read(buf);
in.skip(1024);
bytesRead+=1024;
错误,
in.read(buf)
返回读取的字节数,并将流位置设置为当前位置old position+n read bytes。因此,您不需要跳过——这是一个错误,因为read已经定位了流

验证文件的校验和以确保它们是相同的。(使用md5或其他东西) 我很确定校验和和和文件大小都不一样


您应该使用来进行文件处理。否则,请看。

您的复制代码是完整的,完全是A级废话。Java中复制流的规范方法如下:

int count;
byte[] buffer = new byte[8192]; // or more if you like
while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}

除去所有其他绒毛。这只是浪费时间和空间,显然会在传输过程中损坏您的数据。

您的复制代码是完整的,完全是A级废话。Java中复制流的规范方法如下:

int count;
byte[] buffer = new byte[8192]; // or more if you like
while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}

除去所有其他绒毛。这只是浪费时间和空间,显然会在传输过程中损坏您的数据。

谢谢您的回答。代码是应用程序的一部分,它不仅仅是复制数据(尽管我的问题在于复制部分)。中的部分已读(buf);是我复制数据的地方。其余部分是应用程序所必需的,需要暂停和恢复。也许我所说的方式让它看起来毫无意义,但相信我,它是值得的。@RadAl相信我,你的代码中有几段毫无意义的东西,从每次循环分配一个新的缓冲区开始,调用skip(),一个新的代码块来处理最终的缓冲区加载,忽略read()返回的结果。。。我可以继续。除了将字节复制到EOS之外,您可能还有更多的工作要做,但是您需要研究上面正确而简洁的循环,以了解它为什么会工作,以及为什么您自己的代码从根本上存在缺陷。此外,我假设您的代码片段中有一个输出流。。我需要把内容放进缓冲区。那我怎么处理呢?将输入流中的内容以块的形式写入缓冲区?@RadAl您可以使用此代码写入ByteArrayOutputStream,或者您可以调用value.set(buffer,0,count),假设这样做是正确的,但如果文件太大,我会先将其假脱机到磁盘,而不是尝试将其放入内存,稍后再处理。谢谢你的回答。代码是应用程序的一部分,它不仅仅是复制数据(尽管我的问题在于复制部分)。中的部分已读(buf);是我复制数据的地方。其余部分是应用程序所必需的,需要暂停和恢复。也许我所说的方式让它看起来毫无意义,但相信我,它是值得的。@RadAl相信我,你的代码中有几段毫无意义的东西,从每次循环分配一个新的缓冲区开始,调用skip(),一个新的代码块来处理最终的缓冲区加载,忽略read()返回的结果。。。我可以继续。除了将字节复制到EOS之外,您可能还有更多的工作要做,但是您需要研究上面正确而简洁的循环,以了解它为什么会工作,以及为什么您自己的代码从根本上存在缺陷。此外,我假设您的代码片段中有一个输出流。。我需要把内容放进缓冲区。那我怎么处理呢?将输入流中的内容以块的形式写入缓冲区?@RadAl您可以使用此代码写入ByteArrayOutputStream,也可以只调用value.set(buffer,0,count),假设这样做是正确的,但如果文件太大,我会先将其假脱机到磁盘,而不是尝试将其装入内存,然后再进行处理。