Is it smarter to stream in large strings from an external .txt file, or to simply code them directly in?

StackOverflow https://stackoverflow.com/questions/17995884

  •  04-06-2022
  •  | 
  •  

Pergunta

I'm working in Java, though I'm sure this question extends to multiple other languages and situations.

If I am periodically displaying large chunks of text in a JTextPane,

Is it better to write them into a .txt file and periodically call upon a Scanner to read said file and throw it into the JTextPane,

OR should I simply write the text directly into my code as strings and then have them displayed in the JTextPane?

Is one method more proper than the other? I know the "write it all into the code" method would end up giving me HUGE methods and some uglier code than I'm used to. However, certain situations require different bits of text to be included or excluded.

In case the desired application makes the question easier to answer, I'm playing at making a text-based adventure with RPG elements to practice my Java coding. Not at all professional, just concept practice. Thus, I have to alternate between large chunks of story-telling and smaller questions and situations dependent upon the player's previous choices.

I'm new to having to deal with large amounts of text in my coding, so thanks all who answer!

Foi útil?

Solução

It's always better to have it in a separate file, preferably in the JAR itself, so you can easily reach it with getResourceAsStream().

You can then easily edit this file without messing with code, and you can also modify it after the app is compiled to JAR.

It's a good practice to divide logic from data, in general.


Here are some methods from my FileUtils class you might like:

public static String streamToString(InputStream in) {

    BufferedReader br = null;
    StringBuilder sb = new StringBuilder();

    String line;
    try {

        br = new BufferedReader(new InputStreamReader(in));
        while ((line = br.readLine()) != null) {
            sb.append(line + "\n");
        }

    } catch (IOException e) {
        Log.e(e);
    } finally {
        if (br != null) {
            try {
                br.close();
            } catch (IOException e) {
                Log.e(e);
            }
        }
    }

    return sb.toString();
}


public static InputStream stringToStream(String text) {

    try {
        return new ByteArrayInputStream(text.getBytes("UTF-8"));
    } catch (UnsupportedEncodingException e) {
        Log.e(e);
        return null;
    }
}


public static InputStream getResource(String path) {

    return FileUtils.class.getResourceAsStream(path);
}

You can also use a SimpleConfig class to parse lists and maps from files:
(comment out the Log.something calls and replace with System.err.println())

package net.mightypork.rpack.utils;


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;


/**
 * Utility for parsing simple config files<br>
 * # and // mark a comment<br>
 * empty lines and lines without "=" are ignored<br>
 * lines with "=" must have "key = value" format, or a warning is logged.<br>
 * use "NULL" to create empty value.
 * 
 * @author MightyPork
 */
public class SimpleConfig {

    /**
     * Load list from file
     * 
     * @param file file
     * @return map of keys and values
     * @throws IOException
     */
    public static List<String> listFromFile(File file) throws IOException {

        String fileText = FileUtils.fileToString(file);

        return listFromString(fileText);
    }


    /**
     * Load map from file
     * 
     * @param file file
     * @return map of keys and values
     * @throws IOException
     */
    public static Map<String, String> mapFromFile(File file) throws IOException {

        String fileText = FileUtils.fileToString(file);

        return mapFromString(fileText);
    }


    /**
     * Load list from string
     * 
     * @param text text of the file
     * @return map of keys and values
     */
    public static List<String> listFromString(String text) {

        List<String> list = new ArrayList<String>();

        String[] groupsLines = text.split("\n");

        for (String s : groupsLines) {
            // ignore invalid lines
            if (s.length() == 0) continue;
            if (s.startsWith("#") || s.startsWith("//")) continue;

            // NULL value
            if (s.equalsIgnoreCase("NULL")) s = null;

            if (s != null) s = s.replace("\\n", "\n");

            // save extracted key-value pair
            list.add(s);
        }

        return list;
    }


    /**
     * Load map from string
     * 
     * @param text text of the file
     * @return map of keys and values
     */
    public static Map<String, String> mapFromString(String text) {

        LinkedHashMap<String, String> pairs = new LinkedHashMap<String, String>();

        String[] groupsLines = text.split("\n");

        for (String s : groupsLines) {
            // ignore invalid lines
            if (s.length() == 0) continue;
            if (s.startsWith("#") || s.startsWith("//")) continue;
            if (!s.contains("=")) continue;

            // split and trim
            String[] parts = s.split("=");
            for (int i = 0; i < parts.length; i++) {
                parts[i] = parts[i].trim();
            }

            // check if both parts are valid
            if (parts.length == 0) {
                Log.w("Bad line in config file: " + s);
                continue;
            }

            if (parts.length == 1) {
                parts = new String[] { parts[0], "" };
            }

            if (parts.length != 2) {
                Log.w("Bad line in config file: " + s);
                continue;
            }


            // NULL value
            if (parts[0].equalsIgnoreCase("NULL")) parts[0] = null;
            if (parts[1].equalsIgnoreCase("NULL")) parts[1] = null;

            if (parts[0] != null) parts[0] = parts[0].replace("\\n", "\n");
            if (parts[1] != null) parts[1] = parts[1].replace("\\n", "\n");

            // save extracted key-value pair
            pairs.put(parts[0], parts[1]);
        }

        return pairs;
    }


    /**
     * Save map to file
     * 
     * @param target
     * @param data
     * @throws IOException
     */
    public static void mapToFile(File target, Map<String, String> data) throws IOException {

        String text = ""; //# File written by SimpleConfig

        for (Entry<String, String> e : data.entrySet()) {
            if (text.length() > 0) text += "\n";

            String key = e.getKey();
            String value = e.getValue();

            if (key == null) key = "NULL";
            if (value == null) value = "NULL";

            key = key.replace("\n", "\\n");
            value = value.replace("\n", "\\n");

            text += key + " = " + value;
        }

        FileUtils.stringToFile(target, text);

    }


    /**
     * Save list to file
     * 
     * @param target
     * @param data
     * @throws IOException
     */
    public static void listToFile(File target, List<String> data) throws IOException {

        String text = ""; //# File written by SimpleConfig

        for (String s : data) {
            if (text.length() > 0) text += "\n";

            if (s == null) s = "NULL";

            s = s.replace("\n", "\\n");

            text += s;
        }

        FileUtils.stringToFile(target, text);

    }
}

Outras dicas

It's better to have separate file. One of the reason is that at some point you'd like to be able to translate your game to different languages.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top