我具有以下格式的文件结构
s3://<bucket>/year=2018/month=11/day=26/hour=10/department=x/part-xxxxx.gz.parquet
我的AWS凭证无法访问所有department=
值,只有少数几个。
我正在尝试
df = spark.read.parquet("s3://<bucket>/year=2018/")
以
失败java.io.IOException: Could not read footer: java.io.IOException: Could not read footer for file FileStatus{path=s3://<bucket>/year=2018/month=11/day=26/hour=10/department=yyyyyy/part-xxxxx.gz.parquet; isDirectory=false; length=104448; replication=0; blocksize=0; modification_time=0; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}
它显然失败了,因为我只能访问department=x
而不能访问department=yyyy
,我的问题是:有没有办法让它们默默地忽略那些内容?
我当前的解决方法是像这样构造仅有效路径:
tmpl = 's3://<bucket>/year=2018/month=11/day=26/hour={hour}/department=x/'
df = spark.read.parquet(*list(tmpl.format(hour=hour) for hour in range(1,24)))
非常麻烦,因为
spark.read.parquet
不会将列表或生成器作为输入,因此我被迫使用splat / unpack运算符将所有内容转换为单独的参数。不确定是否可以在数千条路径中使用。 有没有更好的方式来加载此数据而无需更改文件结构(我不控制)?
答案 0 :(得分:1)
它显然失败了,因为我只能访问部门= x而不能访问 department = yyyy,我的问题是:有没有办法默默地 忽略那些?
根据文件状态对象,您对日志中提到的文件具有读写访问权限(permission=rw-rw-rw-
)。文件路径可能是其他问题。
java.io.IOException:无法读取页脚:java.io.IOException:无法 无法读取文件的页脚 FileStatus {path = s3:///year=2018/month=11/day=26/hour=10/department=yyyyyy/part-xxxxx.gz.parquet; isDirectory = false;长度= 104448;复制= 0;块大小= 0; modify_time = 0; access_time = 0;所有者=;组=; 权限= rw-rw-rw-; isSymlink = false}
由于上述错误,您正在以不正确的字符串格式传递fileStatus对象。
您必须通过fileStat.getPath.toString
,也就是说,您必须通过path=s3:///year=2018/month=11/day=26/hour=10/department=yyyyyy/part-xxxxx.gz.parquet;
df = spark.read.parquet(...)将起作用。
如果要传递镶木地板文件夹,则可以传递。
或者您想在示例代码scala片段下方过滤某些文件,您可以使用
/**
* getAllFilePath.
*
* @param filePath Path
* @param fs FileSystem
* @return list of absolute file path present in given path
* @throws FileNotFoundException
* @throws IOException
*/
@throws[FileNotFoundException]
@throws[IOException]
def getAllFilePath(filePath: Path, fs: FileSystem): ListBuffer[String] = {
val fileList = new ListBuffer[String]
val fileStatus = fs.listStatus(filePath)
for (fileStat <- fileStatus) {
logInfo(s"file path Name : ${fileStat.getPath.toString} length is ${fileStat.getLen}")
if (fileStat.isDirectory) fileList ++= (getAllFilePath(fileStat.getPath, fs))
else if (fileStat.getLen > 0 && !fileStat.getPath.toString.isEmpty) {
logInfo("fileStat.getPath.toString" + fileStat.getPath.toString)
fileList.foreach(println)
fileList += fileStat.getPath.toString
} else if (fileStat.getLen == 0) {
logInfo(" length zero files \n " + fileStat)
// fs.rename(fileStat.getPath, new Path(fileStat.getPath+"1"))
}
}
fileList
}
像这个例子
val fs = FileSystem.get(new URI(inputPath), spark.sparkContext.hadoopConfiguration)
yourFiles = getAllFilePath(new Path(inputPath), fs)
val df = spark.read.parquet(yourFiles:_*)