2015-04-02 59 views
5

我正在尋找使用java.nio.file.Files中的功能向任何類型的文件添加自定義元數據標記。我已經能夠正確地讀取元數據,但每當我嘗試設置元數據時都會遇到問題。使用Java nio編寫文件元數據的問題

我試圖設置自定義元數據元素使用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中

,如果我嘗試這個字符串轉換爲字節緩衝區像這樣

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(); 
    } 

,而不是輸出文本「測試」,它輸出的怪字符串「[B @ 14e3f41」

什麼是一個字符串轉換爲字節緩衝區,並將它是可轉換回字符串的正確方法,是否有更多的可定製的方式來修改使用java的文件的元數據?

回答

4

用戶定義的屬性,即由UserDefinedFileAttributeView(前提是您的FileSystem支持它們!)定義的任何屬性,都可以從Java讀取/寫入爲字節數組;如果一個給定的屬性包含文本內容,那麼這個過程將依賴於所討論的字符串的編碼。

現在,您使用的是.{get,set}Attribute()方法,這意味着你有兩個選擇寫user屬性:

  • 或者使用一個ByteBuffer像你這樣;或使用普通字節數組的

你會怎樣讀取然而,它總是一個字節數組。

從上面(重點煤礦)的Javadoc鏈接:

凡屬性是需要文件的動態訪問,getAttribute方法可以被用於讀出的屬性值。 屬性值作爲字節數組返回(byte [])。 setAttribute方法可用於從緩衝區(如通過調用寫入方法)或字節數組(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); 

現在,一旦您在您的處置有這種說法,您可以讀取或寫入,它。例如,以下是你如何閱讀你的特定屬性;注意,這裏我們只使用屬性,因爲視圖(名稱"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這樣的東西。

+0

感謝您的詳細回覆,它幫助解決了這個問題,但這是否意味着任何用戶定義的任何數據類型標籤本來可能必須首先在寫入時編碼到一個字節數組中,並解碼爲匹配類型任何時候他們的意圖被讀? – lobobabysaurus 2015-04-02 19:41:28

+0

@PhilSimmons確實,它意味着這一點;用戶定義的屬性可以是字面上的任何內容,不僅僅是文本內容! – fge 2015-04-02 19:42:28

+0

@PhilSimmons注意到還有另一個選項來讀/寫屬性(通過'View');這是一個更復雜一點,但 – fge 2015-04-02 19:48:50