📄 mutablesection.java
字号:
return sectionBytes.length; } /** * <p>Writes this section into an output stream.</p> * * <p>Internally this is done by writing into three byte array output * streams: one for the properties, one for the property list and one for * the section as such. The two former are appended to the latter when they * have received all their data.</p> * * @param out The stream to write into. * * @return The number of bytes written, i.e. the section's size. * @exception IOException if an I/O error occurs * @exception WritingNotSupportedException if HPSF does not yet support * writing a property's variant type. */ public int write(final OutputStream out) throws WritingNotSupportedException, IOException { /* Check whether we have already generated the bytes making out the * section. */ if (!dirty && sectionBytes != null) { out.write(sectionBytes); return sectionBytes.length; } /* The properties are written to this stream. */ final ByteArrayOutputStream propertyStream = new ByteArrayOutputStream(); /* The property list is established here. After each property that has * been written to "propertyStream", a property list entry is written to * "propertyListStream". */ final ByteArrayOutputStream propertyListStream = new ByteArrayOutputStream(); /* Maintain the current position in the list. */ int position = 0; /* Increase the position variable by the size of the property list so * that it points behind the property list and to the beginning of the * properties themselves. */ position += 2 * LittleEndian.INT_SIZE + getPropertyCount() * 2 * LittleEndian.INT_SIZE; /* Writing the section's dictionary it tricky. If there is a dictionary * (property 0) the codepage property (property 1) must be set, too. */ int codepage = -1; if (getProperty(PropertyIDMap.PID_DICTIONARY) != null) { final Object p1 = getProperty(PropertyIDMap.PID_CODEPAGE); if (p1 != null) { if (!(p1 instanceof Integer)) throw new IllegalPropertySetDataException ("The codepage property (ID = 1) must be an " + "Integer object."); } else /* Warning: The codepage property is not set although a * dictionary is present. In order to cope with this problem we * add the codepage property and set it to Unicode. */ setProperty(PropertyIDMap.PID_CODEPAGE, (long) Variant.VT_I2, new Integer(Constants.CP_UNICODE)); codepage = getCodepage(); } /* Sort the property list by their property IDs: */ Collections.sort(preprops, new Comparator() { public int compare(final Object o1, final Object o2) { final Property p1 = (Property) o1; final Property p2 = (Property) o2; if (p1.getID() < p2.getID()) return -1; else if (p1.getID() == p2.getID()) return 0; else return 1; } }); /* Write the properties and the property list into their respective * streams: */ for (final ListIterator i = preprops.listIterator(); i.hasNext();) { final MutableProperty p = (MutableProperty) i.next(); final long id = p.getID(); /* Write the property list entry. */ TypeWriter.writeUIntToStream(propertyListStream, p.getID()); TypeWriter.writeUIntToStream(propertyListStream, position); /* If the property ID is not equal 0 we write the property and all * is fine. However, if it equals 0 we have to write the section's * dictionary which has an implicit type only and an explicit * value. */ if (id != 0) /* Write the property and update the position to the next * property. */ position += p.write(propertyStream, getCodepage()); else { if (codepage == -1) throw new IllegalPropertySetDataException ("Codepage (property 1) is undefined."); position += writeDictionary(propertyStream, dictionary, codepage); } } propertyStream.close(); propertyListStream.close(); /* Write the section: */ byte[] pb1 = propertyListStream.toByteArray(); byte[] pb2 = propertyStream.toByteArray(); /* Write the section's length: */ TypeWriter.writeToStream(out, LittleEndian.INT_SIZE * 2 + pb1.length + pb2.length); /* Write the section's number of properties: */ TypeWriter.writeToStream(out, getPropertyCount()); /* Write the property list: */ out.write(pb1); /* Write the properties: */ out.write(pb2); int streamLength = LittleEndian.INT_SIZE * 2 + pb1.length + pb2.length; return streamLength; } /** * <p>Writes the section's dictionary.</p> * * @param out The output stream to write to. * @param dictionary The dictionary. * @param codepage The codepage to be used to write the dictionary items. * @return The number of bytes written * @exception IOException if an I/O exception occurs. */ private static int writeDictionary(final OutputStream out, final Map dictionary, final int codepage) throws IOException { int length = TypeWriter.writeUIntToStream(out, dictionary.size()); for (final Iterator i = dictionary.keySet().iterator(); i.hasNext();) { final Long key = (Long) i.next(); final String value = (String) dictionary.get(key); if (codepage == Constants.CP_UNICODE) { /* Write the dictionary item in Unicode. */ int sLength = value.length() + 1; if (sLength % 2 == 1) sLength++; length += TypeWriter.writeUIntToStream(out, key.longValue()); length += TypeWriter.writeUIntToStream(out, sLength); final char[] ca = value.toCharArray(); for (int j = 0; j < ca.length; j++) { int high = (ca[j] & 0x0ff00) >> 8; int low = (ca[j] & 0x000ff); out.write(low); out.write(high); length += 2; sLength--; } while (sLength > 0) { out.write(0x00); out.write(0x00); length += 2; sLength--; } } else { /* Write the dictionary item in another codepage than * Unicode. */ length += TypeWriter.writeUIntToStream(out, key.longValue()); length += TypeWriter.writeUIntToStream(out, value.length() + 1); final byte[] ba = value.getBytes(VariantSupport.codepageToEncoding(codepage)); for (int j = 0; j < ba.length; j++) { out.write(ba[j]); length++; } out.write(0x00); length++; } } return length; } /** * <p>Overwrites the super class' method to cope with a redundancy: * the property count is maintained in a separate member variable, but * shouldn't.</p> * * @return The number of properties in this section */ public int getPropertyCount() { return preprops.size(); } /** * <p>Gets this section's properties.</p> * * @return this section's properties. */ public Property[] getProperties() { properties = (Property[]) preprops.toArray(new Property[0]); return properties; } /** * <p>Gets a property.</p> * * @param id The ID of the property to get * @return The property or <code>null</code> if there is no such property */ public Object getProperty(final long id) { /* Calling getProperties() ensures that properties and preprops are in * sync.</p> */ getProperties(); return super.getProperty(id); } /** * <p>Sets the section's dictionary. All keys in the dictionary must be * {@link java.lang.Long} instances, all values must be * {@link java.lang.String}s. This method overwrites the properties with IDs * 0 and 1 since they are reserved for the dictionary and the dictionary's * codepage. Setting these properties explicitly might have surprising * effects. An application should never do this but always use this * method.</p> * * @param dictionary The dictionary * * @exception IllegalPropertySetDataException if the dictionary's key and * value types are not correct. * * @see Section#getDictionary() */ public void setDictionary(final Map dictionary) throws IllegalPropertySetDataException { if (dictionary != null) { for (final Iterator i = dictionary.keySet().iterator(); i.hasNext();) if (!(i.next() instanceof Long)) throw new IllegalPropertySetDataException ("Dictionary keys must be of type Long."); for (final Iterator i = dictionary.values().iterator(); i.hasNext();) if (!(i.next() instanceof String)) throw new IllegalPropertySetDataException ("Dictionary values must be of type String."); this.dictionary = dictionary; /* Set the dictionary property (ID 0). Please note that the second * parameter in the method call below is unused because dictionaries * don't have a type. */ setProperty(PropertyIDMap.PID_DICTIONARY, -1, dictionary); /* If the codepage property (ID 1) for the strings (keys and * values) used in the dictionary is not yet defined, set it to * Unicode. */ final Integer codepage = (Integer) getProperty(PropertyIDMap.PID_CODEPAGE); if (codepage == null) setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2, new Integer(Constants.CP_UNICODE)); } else /* Setting the dictionary to null means to remove property 0. * However, it does not mean to remove property 1 (codepage). */ removeProperty(PropertyIDMap.PID_DICTIONARY); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -