我希望使用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'
将String转换为bytebuffer并将其转换回字符串的正确方法是什么?是否有一种更可自定义的方法来使用java修改文件上的元数据?
答案 0 :(得分:4)
用户定义的属性,即UserDefinedFileAttributeView
定义的任何属性(假设您的FileSystem
支持它们!),可以从Java读取/写入字节数组;如果一个给定的属性包含文本内容,那么它将依赖于进程,对于相关字符串的编码将是什么。
现在,您正在使用.{get,set}Attribute()
方法,这意味着您有两个选项来编写user
属性:
ByteBuffer
;或你读取的内容总是如此。
从上面的javadoc链接(强调我的):
如果需要动态访问文件属性,可以使用getAttribute方法读取属性值。 属性值以字节数组(byte [])的形式返回。 setAttribute方法可用于从缓冲区(如通过调用write方法)或字节数组(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
类允许您使用此方法获取任何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
这样的东西。