当前位置: 首页 > 知识库问答 >
问题:

用Java读取远程HDFS文件

严言
2023-03-14

我有一个简单的Hadoop安装有点麻烦。我已经下载了hadoop 2.4.0并安装在一个CentOSLinux节点(虚拟机)上。我已经为apache站点(http://hadoop.apache.org/docs/r2.4.0/hadoop-project-dist/hadoop-common/SingleCluster.html)上描述的具有伪分布的单个节点配置了hadoop。它从日志中没有问题开始,我可以使用命令行中的“hadoop fs”命令读取写文件。

我正在尝试使用JavaAPI从远程机器上的HDFS读取一个文件。机器可以连接并列出目录内容。它还可以确定是否存在包含以下代码的文件:

Path p=new Path("hdfs://test.server:9000/usr/test/test_file.txt");
FileSystem fs = FileSystem.get(new Configuration());
System.out.println(p.getName() + " exists: " + fs.exists(p));

系统打印“true”表示它存在。但是,当我试图读取文件:

BufferedReader br = null;
try {
    Path p=new Path("hdfs://test.server:9000/usr/test/test_file.txt");
    FileSystem fs = FileSystem.get(CONFIG);
    System.out.println(p.getName() + " exists: " + fs.exists(p));

    br=new BufferedReader(new InputStreamReader(fs.open(p)));
    String line = br.readLine();

    while (line != null) {
        System.out.println(line);
        line=br.readLine();
    }
}
finally {
    if(br != null) br.close();
}

此代码引发异常:

异常线程"main"org.apache.hadoop.hdfs.BlockMissing异常:无法获得块:BP-13917963-127.0.0.1-1398476189167:blk_1073741831_1007file=/usr/test/test_file.txt

谷歌给出了一些可能的提示,但都被证实了。数据节点已连接、处于活动状态,并且具有足够的空间。hdfs dfsadmin–报告中的管理报告显示:

配置容量:52844687360 (49.22GB)
当前容量:48507940864 (45.18GB)
DFS剩余:48507887616 (45.18GB)
DFS使用: 53248(52 KB)
DFS使用%: 0.00%
下复制块: 0
具有损坏副本的块:0
缺少块:0

可用数据:1(总共1个,0个死亡)

实时数据:
名称:127.0.0.1:50010(test.server)
主机名:test.server
退役状态:正常
配置容量:52844687360 (49.22GB)
DFS使用:53248(52 KB)
非DFS使用:4336746496 (4.04GB)
DFS剩余:48507887616 (45.18GB)<配置的缓存容量:0(0 B)
使用的缓存:0(0 B)
缓存剩余:0(0 B)
使用的缓存%:100.00%
缓存剩余%:0.00%
最后联系: Fri Apr25 22:16:56PDT 2014

客户端罐是直接从hadoop安装复制的,所以没有版本不匹配。我可以用我的Java类浏览文件系统并读取文件属性。我只是不能读取文件内容没有得到例外。如果我试图用代码写一个文件:

FileSystem fs = null;
BufferedWriter br = null;

System.setProperty("HADOOP_USER_NAME", "root");

try {
    fs = FileSystem.get(new Configuraion());

    //Path p = new Path(dir, file);
    Path p = new Path("hdfs://test.server:9000/usr/test/test.txt");
    br = new BufferedWriter(new OutputStreamWriter(fs.create(p,true)));
    br.write("Hello World");
}
finally {
    if(br != null) br.close();
    if(fs != null) fs.close();
}

这将创建文件,但不写入任何字节并引发异常:

线程“main”组织中出现异常。阿帕奇。hadoop。ipc。RemoteException(java.io.IOException):文件/usr/test/test。txt只能复制到0个节点,而不是minReplication(=1)。此操作中有1个数据节点正在运行,1个节点被排除。

谷歌搜索表明可能存在空间问题,但从dfsadmin报告来看,空间似乎很大。这是一个普通的安装,我不能通过这个问题。

环境总结为:

服务器:

具有伪分布的Hadoop 2.4.0(http://hadoop.apache.org/docs/r2.4.0/hadoop-project-dist/hadoop-common/SingleCluster.html)

CentOS 6.5虚拟机64位服务器Java1.70_55

客户:

Windows 8(虚拟机)Java1.70_51

任何帮助都非常感谢。

共有3个答案

公孙英飙
2023-03-14

上面的答案指向了正确的方向。请允许我添加以下内容:

  1. Namenode不会直接读写数据。
  2. 客户端(使用直接访问HDFS的Java程序)与Namenode交互,以更新HDFS命名空间并检索用于读取/写入的块位置。
  3. 客户端直接与Datanode交互以读取/写入数据。

您之所以能够列出目录内容,是因为您的客户端代码可以访问hostname:9000。你在做上面的第二个动作
要能够读写,您的客户端代码需要访问Datanode(编号3)。Datanode DFS数据传输的默认端口为50010。有东西阻止了您与主机名50010的客户端通信。可能是防火墙或SSH隧道配置问题
我使用的是Hadoop 2.7.2,所以您可能有不同的端口号设置。

孟昊空
2023-03-14

我们需要确保使用fs进行配置。违约名称空间集,例如

配置。集合(“fs.default.name”hdfs://ourHDFSNameNode:50000”;

下面我放了一段示例代码

 Configuration configuration = new Configuration();
 configuration.set("fs.default.name","hdfs://ourHDFSNameNode:50000");
 FileSystem fs = pt.getFileSystem(configuration);
 BufferedReader br = new BufferedReader(new InputStreamReader(fs.open(pt)));
 String line = null;
 line = br.readLine
 while (line != null) {
  try {
    line = br.readLine
    System.out.println(line);
  }
}
阴凯歌
2023-03-14

Hadoop错误消息令人沮丧。他们往往不说出自己的意思,与真正的问题无关。我见过当客户机、namenode和datanode无法正常通信时会出现这样的问题。在您的情况下,我将从两个问题中选择一个:

  • 您的群集在VM中运行,其对客户端的虚拟化网络访问被阻止
  • 您没有始终使用在客户端和主机之间解析相同的完全限定域名(FQDN)

主机名“test.server”很可疑。检查以下所有内容:

  • 这是测试。服务器FQDN

必须删除FQDN、主机名、数字IP和localhost使用中的任何不一致之处。永远不要在conf文件或客户端代码中混合它们。一致使用FQDN是首选。数字IP的一致使用通常也可以。使用不合格的主机名、localhost或127.0.0.1会导致问题。

 类似资料:
  • 问题内容: 我正在寻找一种简单的方法来获取位于远程服务器上的文件。为此,我在Windows XP上创建了本地ftp服务器,现在我想为测试Applet提供以下地址: 当然,我会收到以下错误: URI方案不是“文件” 我一直在尝试其他方法来获取文件,但它们似乎没有用。我该怎么办?(我也很想执行HTTP请求) 问题答案: 您不能使用ftp开箱即用。 如果文件位于http上,则可以执行以下操作: 如果要使

  • 问题内容: 我从在远程Ubuntu机器上的目录中读写文件的要求开始。 首先,我编写了一个Java程序,该程序可以从远程Windows计算机(即LAN)上的共享文件夹读取,写入文件。在这里,这样的事情在我的(本地)Windows计算机上起作用: 现在,当我考虑使用远程Ubuntu计算机时,显然我无法执行此类操作,因为该计算机不在LAN上( 我不确定即使在LAN上也可以做到 )。因此,我尝试了以下方法

  • 所以我必须检索存储在HDFS中的文件的内容,并对其进行某些分析。 问题是,我甚至无法读取文件并将其内容写入本地文件系统中的另一个文本文件。(我是Flink的新手,这只是一个测试,以确保我正确读取了文件) HDFS中的文件是纯文本文件。这是我的密码: 在我运行/tmp之后,它没有输出。 这是一个非常简单的代码,我不确定它是否有问题,或者我只是做了一些别的错误。正如我所说,我对Flink完全是新手 此

  • 问题内容: 我正在寻找一种无需实际下载文件即可从远程服务器上的MP3文件读取ID3标签的方法。我见过像JAudioTagger和Entagged这样的库,但是它们似乎都需要一个文件对象,而不是URL或InputStream,我知道该如何获取远程文件。是否有另一个图书馆可以做到这一点?还是有办法使用URL获取正确的对象与这些类进行交互? 问题答案: 本页介绍如何获取MP3文件的ID3 V.1 标签。

  • 我已经考虑了很长一段时间了。我正在尝试从雅虎的股票API下载数据。当您使用 API 时,它会为您提供一个文件。我一直在看opencsv,这似乎很完美,除了我想避免下载和保存文件,如果可能的话。 根据示例,OpenCSV只能从中读取。根据Oracle关于的文档,文件需要是本地的。 是否可以使用 OpenCSV 从远程文件读取而不下载?

  • 我正在尝试使用Saxon 9将csv文件转换为xml文件。但是当我尝试检查存在并读取带有xslt函数的csv文件时,我遇到了一个问题:unparsed-text-可用(),unparsed-text() 它们可以很好地处理本地文件,但当我将远程文件作为参数传递时,unparsed-text-available()返回false。 例如,当我通过“D:\test\test.csv”时,它就工作了。当