使用 Java nio 写入文件元数据时出现问题
Issues writing file metadata with Java nio
我希望使用 java.nio.file.Files 中的功能向任何类型的文件添加自定义元数据标签。我已经能够正确读取元数据,但每当我尝试设置元数据时都会遇到问题。
我尝试使用 Files.setAttribute 和以下
来设置带有纯字符串的自定义元数据元素
Path photo = Paths.get("C:\Users\some\picture\path\2634.jpeg");
try{
BasicFileAttributes attrs = Files.readAttributes(photo, BasicFileAttributes.class);
Files.setAttribute(photo, "user:tags", "test");
String attribute = Files.getAttribute(photo, "user:tags").toString();
System.out.println(attribute);
}
catch (IOException ioex){
ioex.printStackTrace();
}
但最终出现以下错误:
线程 "main" java.lang.ClassCastException 中的异常:java.lang.String 无法转换为 java.nio.ByteBuffer
如果我像这样尝试将该字符串转换为 ByteBuffer
Path photo = Paths.get("C:\Users\some\picture\path\2634.jpeg");
try{
BasicFileAttributes attrs = Files.readAttributes(photo, BasicFileAttributes.class);
Files.setAttribute(photo, "user:tags", ByteBuffer.wrap(("test").getBytes("UTF-8")));
String attribute = Files.getAttribute(photo, "user:tags").toString();
System.out.println(attribute);
}
catch (IOException ioex){
ioex.printStackTrace();
}
输出的不是文本'test',而是奇怪的字符串'[B@14e3f41'
将字符串转换为字节缓冲区并将其转换回字符串的正确方法是什么?是否有更可自定义的方法来使用 java 修改文件上的元数据?
用户定义的属性,即UserDefinedFileAttributeView
定义的任何属性(前提是你的FileSystem
支持它们!),是readable/writable来自Java的字节数组;如果给定属性包含文本内容,则相关字符串的编码取决于进程。
现在,您正在使用 .{get,set}Attribute()
方法,这意味着您有两种选择来编写 user
属性:
- 或者像你一样使用
ByteBuffer
;或者
- 使用普通字节数组。
您将从中读取的内容始终是字节数组。
来自上面的 javadoc link(强调我的):
Where dynamic access to file attributes is required, the getAttribute method may be used to read the attribute value. The attribute value is returned as a byte array (byte[]). The setAttribute method may be used to write the value of a user-defined attribute from a buffer (as if by invoking the write method), or byte array (byte[]).
所以,在你的情况下:
为了写入 属性,从您的字符串中获取具有请求编码的字节数组:
final Charset utf8 = StandardCharsets.UTF_8;
final String myAttrValue = "Mémé dans les orties";
final byte[] userAttributeValue = myAttrValue.getBytes(utf8);
Files.setAttribute(photo, "user:tags", userAttributeValue);
为了读取属性,你需要将.getAttribute()
的结果转换为一个字节数组,然后得到一个字符串,再次使用正确的编码:
final Charset utf8 = StandardCharsets.UTF_8;
final byte[] userAttributeValue
= (byte[]) Files.readAttribute(photo, "user:tags");
final String myAttrValue = new String(userAttributeValue, utf8);
查看其他解决方案,以防万一...
前面已经说过,你要处理的是一个UserDefinedFileAttributeView
。 Files
class 允许您使用此方法获得任何 FileAttributeView
实现:
final UserDefinedFileAttributeView view
= Files.getFileAttributeView(photo, UserDefinedFileAttributeView.class);
现在,一旦有了这个视图,您就可以对其进行读取或写入。
例如,这是您读取特定属性的方式;请注意,这里我们只使用属性 name,因为视图(名称 "user"
)已经存在:
final Charset utf8 = StandardCharsets.UTF_8;
final int attrSize = view.size("tags");
final ByteBuffer buf = ByteBuffer.allocate(attrSize);
view.read("tags", buf);
return new String(buf.array(), utf8);
为了写入,您需要将字节数组包装成 ByteBuffer
:
final Charset utf8 = StandardCharsets.UTF_8;
final int array = tagValue.getBytes(utf8);
final ByteBuffer buf = ByteBuffer.wrap(array);
view.write("tags", buf);
就像我说的,它给了你更多的控制权,但也更复杂。
最后说明:顾名思义,用户定义的属性是用户定义的;此视图的给定属性可能存在,也可能不存在。如果属性不存在等,您有责任正确处理错误;对于这种情况,JDK 没有提供 NoSuchAttributeException
这样的东西。
我希望使用 java.nio.file.Files 中的功能向任何类型的文件添加自定义元数据标签。我已经能够正确读取元数据,但每当我尝试设置元数据时都会遇到问题。
我尝试使用 Files.setAttribute 和以下
来设置带有纯字符串的自定义元数据元素 Path photo = Paths.get("C:\Users\some\picture\path\2634.jpeg");
try{
BasicFileAttributes attrs = Files.readAttributes(photo, BasicFileAttributes.class);
Files.setAttribute(photo, "user:tags", "test");
String attribute = Files.getAttribute(photo, "user:tags").toString();
System.out.println(attribute);
}
catch (IOException ioex){
ioex.printStackTrace();
}
但最终出现以下错误:
线程 "main" java.lang.ClassCastException 中的异常:java.lang.String 无法转换为 java.nio.ByteBuffer
如果我像这样尝试将该字符串转换为 ByteBuffer
Path photo = Paths.get("C:\Users\some\picture\path\2634.jpeg");
try{
BasicFileAttributes attrs = Files.readAttributes(photo, BasicFileAttributes.class);
Files.setAttribute(photo, "user:tags", ByteBuffer.wrap(("test").getBytes("UTF-8")));
String attribute = Files.getAttribute(photo, "user:tags").toString();
System.out.println(attribute);
}
catch (IOException ioex){
ioex.printStackTrace();
}
输出的不是文本'test',而是奇怪的字符串'[B@14e3f41'
将字符串转换为字节缓冲区并将其转换回字符串的正确方法是什么?是否有更可自定义的方法来使用 java 修改文件上的元数据?
用户定义的属性,即UserDefinedFileAttributeView
定义的任何属性(前提是你的FileSystem
支持它们!),是readable/writable来自Java的字节数组;如果给定属性包含文本内容,则相关字符串的编码取决于进程。
现在,您正在使用 .{get,set}Attribute()
方法,这意味着您有两种选择来编写 user
属性:
- 或者像你一样使用
ByteBuffer
;或者 - 使用普通字节数组。
您将从中读取的内容始终是字节数组。
来自上面的 javadoc link(强调我的):
Where dynamic access to file attributes is required, the getAttribute method may be used to read the attribute value. The attribute value is returned as a byte array (byte[]). The setAttribute method may be used to write the value of a user-defined attribute from a buffer (as if by invoking the write method), or byte array (byte[]).
所以,在你的情况下:
为了写入 属性,从您的字符串中获取具有请求编码的字节数组:
final Charset utf8 = StandardCharsets.UTF_8; final String myAttrValue = "Mémé dans les orties"; final byte[] userAttributeValue = myAttrValue.getBytes(utf8); Files.setAttribute(photo, "user:tags", userAttributeValue);
为了读取属性,你需要将
.getAttribute()
的结果转换为一个字节数组,然后得到一个字符串,再次使用正确的编码:final Charset utf8 = StandardCharsets.UTF_8; final byte[] userAttributeValue = (byte[]) Files.readAttribute(photo, "user:tags"); final String myAttrValue = new String(userAttributeValue, utf8);
查看其他解决方案,以防万一...
前面已经说过,你要处理的是一个UserDefinedFileAttributeView
。 Files
class 允许您使用此方法获得任何 FileAttributeView
实现:
final UserDefinedFileAttributeView view
= Files.getFileAttributeView(photo, UserDefinedFileAttributeView.class);
现在,一旦有了这个视图,您就可以对其进行读取或写入。
例如,这是您读取特定属性的方式;请注意,这里我们只使用属性 name,因为视图(名称 "user"
)已经存在:
final Charset utf8 = StandardCharsets.UTF_8;
final int attrSize = view.size("tags");
final ByteBuffer buf = ByteBuffer.allocate(attrSize);
view.read("tags", buf);
return new String(buf.array(), utf8);
为了写入,您需要将字节数组包装成 ByteBuffer
:
final Charset utf8 = StandardCharsets.UTF_8;
final int array = tagValue.getBytes(utf8);
final ByteBuffer buf = ByteBuffer.wrap(array);
view.write("tags", buf);
就像我说的,它给了你更多的控制权,但也更复杂。
最后说明:顾名思义,用户定义的属性是用户定义的;此视图的给定属性可能存在,也可能不存在。如果属性不存在等,您有责任正确处理错误;对于这种情况,JDK 没有提供 NoSuchAttributeException
这样的东西。