【问题标题】:Java File and ByteArray or InputStreamJava 文件和 ByteArray 或 InputStream
【发布时间】:2010-04-24 10:48:06
【问题描述】:

我想使用 jFugue 在小程序中播放一些 MIDI 音乐。 MIDI 模式有一个类 - Pattern - 加载模式的唯一方法是从文件中加载。现在,我不知道小程序如何加载文件以及不知道什么,但我正在使用一个框架(PulpCore),它使加载资产成为一项简单的任务。如果我需要从 ZIP 目录中获取资产,我可以使用提供 get()getAsStream() 方法的 Assets 类。 get()ByteArray 形式返回给定资产,另一个以InputStream 形式返回。

我需要 jFugue 从ByteArrayInputStream 加载模式。 在伪代码中,我想这样做:

Pattern.load(new File(Assets.get("mymidifile.midi")));

但是,没有可以采用 ByteArray 的 File 构造函数。请给点建议?

【问题讨论】:

    标签: java file bytearray jfugue pulpcore


    【解决方案1】:

    确实,jFugue 不允许加载文件以外的任何内容,这很遗憾,因为没有任何东西可以阻止使用任何其他类型的流:

    public static final String TITLE = "Title";
    
    public static Pattern loadPattern(File file) throws IOException {
        InputStream in = new FileInputStream(file);
        try {
            return loadPattern(in);
        } finally {
            in.close();
        }
    }
    
    public static Pattern loadPattern(URL url) throws IOException {
        InputStream in = url.openStream();
        try {
            return loadPattern(in);
        } finally {
            in.close();
        }
    }
    
    public static Pattern loadPattern(InputStream in) throws IOException {
        return loadPattern(new InputStreamReader(in, "UTF-8")); // or ISO-8859-1 ?
    }
    
    public static Pattern loadPattern(Reader reader) throws IOException {
        if (reader instanceof BufferedReader) {
            return loadPattern(reader);
        } else {
            return loadPattern(new BufferedReader(reader));
        }
    }
    
    public static Pattern loadPattern(BufferedReader bread) throws IOException {
        StringBuffer buffy = new StringBuffer();
    
        Pattern pattern = new Pattern();
        while (bread.ready()) {
            String s = bread.readLine();
            if ((s != null) && (s.length() > 1)) {
                if (s.charAt(0) != '#') {
                    buffy.append(" ");
                    buffy.append(s);
                } else {
                    String key = s.substring(1, s.indexOf(':')).trim();
                    String value = s.substring(s.indexOf(':')+1, s.length()).trim();
                    if (key.equalsIgnoreCase(TITLE)) {
                        pattern.setTitle(value);
                    } else {
                        pattern.setProperty(key, value);
                    }
                }
            }
        }
        return pattern;
    }
    

    更新(用于 loadMidi)

    public static Pattern loadMidi(InputStream in) throws IOException, InvalidMidiDataException
    {
        MidiParser parser = new MidiParser();
        MusicStringRenderer renderer = new MusicStringRenderer();
        parser.addParserListener(renderer);
        parser.parse(MidiSystem.getSequence(in));
        Pattern pattern = new Pattern(renderer.getPattern().getMusicString());
        return pattern;
    }
    
    public static Pattern loadMidi(URL url) throws IOException, InvalidMidiDataException
    {
        MidiParser parser = new MidiParser();
        MusicStringRenderer renderer = new MusicStringRenderer();
        parser.addParserListener(renderer);
        parser.parse(MidiSystem.getSequence(url));
        Pattern pattern = new Pattern(renderer.getPattern().getMusicString());
        return pattern;
    }
    

    【讨论】:

    • 使用此代码文件加载没有错误,但不会播放。我现在完全失去理智了。我想要的只是加载一个 MIDI 并播放它。
    • 我猜你应该使用 loadMidi 来加载一个 midi 文件
    【解决方案2】:

    如果我没记错的话,Pattern 文件包含纯文本。使用 getAsStream() 加载文件,然后使用

    将其转换为字符串
    BufferedReader br = new BufferedReader(new InputStreamReader(yourStream));
    //...
    String pattern = convertToString(br); // you should implement convertToString yourself. It's easy. Read the java.io APIs.
    

    其中 yourStream 是 getAsStream() 返回的 InputStream。然后使用 add(String... patterns) 方法加载模式:

    add(pattern);
    

    【讨论】:

    • 这对我来说似乎是最好的选择。您可以在示例页面 (jfugue.org/examples.html) 上看到,如果您愿意,可以使用 Stirng 构建模式。模式 pattern = new Pattern( convertToString( getInputStream() ) );
    • 看起来不错,我试过了,但我收到了错误消息。该文件包含一些非音乐数据、标题、作者或任何它会解析的内容。我选择了下面发布的更完整的示例之一。
    【解决方案3】:

    你可以使用这段代码(取自Pattern.loadPattern()方法的实现):

        InputStream is = ...; // Get a stream from the Asset object
    
        // Prepare a pattern object
        Pattern pattern = new Pattern();
    
        // Now start reaing from the stream
        StringBuffer buffy = new StringBuffer();
        BufferedReader bread = new BufferedReader(new InputStreamReader(is));
        while (bread.ready()) {
            String s = bread.readLine();
            if ((s != null) && (s.length() > 1)) {
                if (s.charAt(0) != '#') {
                    buffy.append(" ");
                    buffy.append(s);
                } else {
                    String key = s.substring(1, s.indexOf(':')).trim();
                    String value = s.substring(s.indexOf(':')+1, s.length()).trim();
                    if (key.equalsIgnoreCase(TITLE)) {
                        pattern.setTitle(value);
                    } else {
                        pattern.setProperty(key, value);
                    }
                }
            }
        }
        bread.close();
        pattern.setMusicString(buffy.toString());
    
        // Your pattern is now ready
    

    【讨论】:

      【解决方案4】:

      您可以读取字节数组并将其转换为字符串。

      问题将出在 InputStream 上。有一个 StringBufferInputStream,但它已被弃用,取而代之的是 StringReader。

      byte [] b = Assets.get();
      InputStream is = new StringBufferInputStream(new String(b));
      Pattern.load(is);
      

      【讨论】:

      • 这除了破坏数据还能做什么?
      • 看看那个——毕竟不是那么远。
      【解决方案5】:

      你不想用File,你想用java.io.ByteArrayInputStream

      【讨论】:

      • 这没什么用,我们被告知 Pattern.load 只接受一个文件作为参数。
      猜你喜欢
      • 2014-04-19
      • 1970-01-01
      • 2013-06-05
      • 1970-01-01
      • 2018-08-05
      • 2012-08-03
      • 1970-01-01
      • 2012-12-19
      • 2014-10-29
      相关资源
      最近更新 更多