使用Java nio编写文件元数据的问题

lob*_*rus 5 java nio metadata file

我希望使用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();
    }
Run Code Online (Sandbox Code Playgroud)

但最终会出现以下错误:

线程"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();
    }
Run Code Online (Sandbox Code Playgroud)

而不是输出文本'test',它输出奇怪的字符串'[B @ 14e3f41'

将String转换为bytebuffer并将其转换回字符串的正确方法是什么?有一种更可自定义的方法来使用java修改File上的元数据吗?

fge*_*fge 4

用户定义的属性,即由UserDefinedFileAttributeView(前提是您FileSystem支持它们!)定义的任何属性,可以作为字节数组从 Java 中读取/写入;如果给定属性包含文本内容,则相关字符串的编码取决于进程。

\n\n

现在,您正在使用这些.{get,set}Attribute()方法,这意味着您有两个选项来编写user属性:

\n\n
    \n
  • ByteBuffer要么像你一样使用;或者
  • \n
  • 使用纯字节数组。
  • \n
\n\n

然而,您从中出的始终是一个字节数组。

\n\n

从上面的 javadoc 链接(强调我的):

\n\n
\n

当需要动态访问文件属性时,可以使用 getAttribute 方法来读取属性值。属性值以字节数组 (byte[]) 的形式返回。setAttribute 方法可用于从缓冲区写入用户定义属性的值(就像通过调用 write 方法一样)或字节数组 (byte[])

\n
\n\n

所以,就你而言:

\n\n
    \n
  • 为了写入属性,请从字符串中获取具有所请求编码的字节数组:

    \n\n
    final Charset utf8 = StandardCharsets.UTF_8;\nfinal String myAttrValue = "M\xc3\xa9m\xc3\xa9 dans les orties";\nfinal byte[] userAttributeValue = myAttrValue.getBytes(utf8);\nFiles.setAttribute(photo, "user:tags", userAttributeValue);\n
    Run Code Online (Sandbox Code Playgroud)
  • \n
  • 为了读取属性,您需要将结果转换.getAttribute()为字节数组,然后从中获取字符串,再次使用正确的编码:

    \n\n
    final Charset utf8 = StandardCharsets.UTF_8;\nfinal byte[] userAttributeValue \n    = (byte[]) Files.readAttribute(photo, "user:tags");\nfinal String myAttrValue = new String(userAttributeValue, utf8);\n
    Run Code Online (Sandbox Code Playgroud)
  • \n
\n\n
\n\n

看看其他解决方案,以防万一......

\n\n

正如已经提到的,您想要处理的是UserDefinedFileAttributeView. 该类Files允许您使用此方法获得任何FileAttributeView实现:

\n\n
final UserDefinedFileAttributeView view\n    = Files.getFileAttributeView(photo, UserDefinedFileAttributeView.class);\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,一旦您可以使用该视图,您就可以对其进行读取或写入。

\n\n

例如,以下是您读取特定属性的方式;请注意,这里我们只使用属性name,因为视图(带有 name "user")已经存在:

\n\n
final Charset utf8 = StandardCharsets.UTF_8;\nfinal int attrSize = view.size("tags");\nfinal ByteBuffer buf = ByteBuffer.allocate(attrSize);\nview.read("tags", buf);\nreturn new String(buf.array(), utf8);\n
Run Code Online (Sandbox Code Playgroud)\n\n

为了写入,您需要将字节数组包装成ByteBuffer

\n\n
final Charset utf8 = StandardCharsets.UTF_8;\nfinal int array = tagValue.getBytes(utf8);\nfinal ByteBuffer buf = ByteBuffer.wrap(array);\nview.write("tags", buf);\n
Run Code Online (Sandbox Code Playgroud)\n\n

就像我说的,它给了你更多的控制权,但也更多地参与其中。

\n\n

最后一点:顾名思义,用户定义的属性是用户定义的;该视图的给定属性可能存在,也可能不存在。如果属性不存在等,您有责任正确处理错误;JDK 没有NoSuchAttributeException为这种情况提供这样的东西。

\n