1

I wrote a program that generates random numbers into two text files and random letters into a third according the two constant files. Now I need to read from each text file, line by line, and put them together. The program is that the suggestion found here doesn't really help my situation. When I try that approach it just reads all lines until it's done without allowing me the option to pause it, go to a different file, etc.

Ideally I would like to find some way to read just the next line, and then later go to the line after that. Like maybe some kind of variable to hold my place in reading or something.

public static void mergeProductCodesToFile(String prefixFile,
                                           String inlineFile,
                                           String suffixFile,
                                           String productFile) throws IOException 
{
    try (BufferedReader br = new BufferedReader(new FileReader(prefixFile))) 
    {
        String line;
        while ((line = br.readLine()) != null) 
            {
                try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(productFile, true))))
                {
                        out.print(line); //This will print the next digit to the right
                }
            catch (FileNotFoundException e) 
                {
                    System.err.println("File error: " + e.getMessage());
                }  
            }
    }
}

EDIT: The digits being created according to the following. Basically, constants tell it how many digits to create in each line and how many lines to create. Now I need to combine these together without deleting anything from either text file.

public static void writeRandomCodesToFile(String codeFile, 
                                          char fromChar, char toChar,
                                          int numberOfCharactersPerCode,
                                          int numberOfCodesToGenerate) throws IOException 
{

    for (int i = 1; i <= PRODUCT_COUNT; i++)
    {
        int I = 0;


        if (codeFile == "inline.txt")
        {

            for (I = 1; I <= CHARACTERS_PER_CODE; I++)
            {
                int digit = (int)(Math.random() * 10);


                try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(codeFile, true))))
                {
                        out.print(digit); //This will print the next digit to the right
                }
                catch (FileNotFoundException e) 
            {
                System.err.println("File error: " + e.getMessage());
                System.exit(1);  
            }

            }
        }

        if ((codeFile == "prefix.txt") || (codeFile == "suffix.txt"))
        {

            for (I = 1; I <= CHARACTERS_PER_CODE; I++)
            {
                Random r = new Random();
                char digit = (char)(r.nextInt(26) + 'a');
                digit = Character.toUpperCase(digit);

                try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(codeFile, true))))
                {
                        out.print(digit);
                }
                catch (FileNotFoundException e) 
            {
                System.err.println("File error: " + e.getMessage());
                System.exit(1);  
            }

            }    
        }
            //This will take the text file to the next line
            if (I >= CHARACTERS_PER_CODE)
            {
                {
                Random r = new Random();
                char digit = (char)(r.nextInt(26) + 'a');

                try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(codeFile, true))))
                {
                        out.println(""); //This will return a new line for the next loop
                }
                catch (FileNotFoundException e) 
            {
                System.err.println("File error: " + e.getMessage());
                System.exit(1);  
            }
                }
            }

    }
    System.out.println(codeFile + " was successfully created.");

}// end writeRandomCodesToFile()
Community
  • 1
  • 1
Elliander
  • 503
  • 1
  • 9
  • 19
  • Presumably you cant store each line in some kind of `Sting[]` or `List` and then interleave them by accessing them there? Different approach, same end result. – D. Ben Knoble Jul 18 '15 at 03:46
  • Ie, 3 data structures for three different files. – D. Ben Knoble Jul 18 '15 at 03:47
  • What about this approach: http://stackoverflow.com/questions/16665124/java-how-to-append-text-to-top-of-file-txt I thought of using an approach like that, but the only problem is that it goes to above the top line instead of to the right of the top line. Since the digits of each line is determined by a constant, I could just add one to that constant, but what would I use to select the place on a given line? – Elliander Jul 18 '15 at 03:52
  • 1
    Im a little bit confused by your discussion of digits on a line and selecting places on a line. Why dont you post an example of your 3 files and what youd want them to look like when put together? Thatll help everybody get a solution going. – D. Ben Knoble Jul 18 '15 at 03:54
  • OK, I just edited the question. For example, ABC123DEF would be the final goal of one file saying ABC, another saying 123, and another saying DEF. The first line of the first three files would correspond to the first line of the fourth. The thing is though I need to be able to change how many digits I would use later as well as how many lines. So in the future it might instead look like ABCD1234EFGH, as an example. Though it's completely random. – Elliander Jul 18 '15 at 04:06
  • I still think storing the data is the best bet, if you can assume that every line has exactly the same number of characters. Ill write up a simple demonstration in the morning using ArrayLists if nobody beats me to it. – D. Ben Knoble Jul 18 '15 at 04:08
  • And each file has the same number of lines. – D. Ben Knoble Jul 18 '15 at 04:10
  • Even though I was given a solution that works, I would still be interested in seeing your approach. Please do share it when you have the time! – Elliander Jul 18 '15 at 06:07

2 Answers2

1

Being respectfull with your code, it will be something like this:

public static void mergeProductCodesToFile(String prefixFile, String inlineFile, String suffixFile, String productFile) throws IOException {
    try (BufferedReader prefixReader = new BufferedReader(new FileReader(prefixFile));
        BufferedReader inlineReader = new BufferedReader(new FileReader(inlineFile));
        BufferedReader suffixReader = new BufferedReader(new FileReader(suffixFile))) {

      StringBuilder line = new StringBuilder();
      String prefix, inline, suffix;
      while ((prefix = prefixReader.readLine()) != null) {
        //assuming that nothing fails and the files are equals in # of lines.
        inline = inlineReader.readLine();
        suffix = suffixReader.readLine();
        line.append(prefix).append(inline).append(suffix).append("\r\n");
        // write it
        ...

      }
    } finally {/*close writers*/}
  }

Some exceptions may be thrown.

I hope you don't implement it in one single method. You can make use of iterators too, or a very simple reader class (method).

I wouldn't use List to load the data at least I guarantee that the files will be low sized and that I can spare the memory usage.

  • hmm. I like the simplicity of your approach, and it definitely works, but when I use my normal approach to writing I can't seem to get it to print to the next line. It all occupies a single line. Any thoughts on what could be causing that? I am using: out.println(line); – Elliander Jul 18 '15 at 04:48
  • you need to add a line jump try this `line.append(prefix).append(inline).append(suffix).append("\r\n");` – Sergio Velasquez Jul 18 '15 at 04:55
1

My approach as we discussed by storing the data and interleaving it. Like Sergio said in his answer, make sure memory isn't a problem in terms of the size of the file and how much memory the data structures will use.

//the main method we're working on
public static void mergeProductCodesToFile(String prefixFile,
                                       String inlineFile,
                                       String suffixFile,
                                       String productFile) throws IOException
{
    try {
        List<String> prefix = read(prefixFile);
        List<String> inline = read(inlineFile);
        List<String> suffix = read(productFile);

        String fileText = interleave(prefix, inline, suffix);
        //write the single string to file however you want
    } catch (...) {...}//do your error handling...
}

//helper methods and some static variables
private static Scanner reader;//I just prefer scanner. Use whatever you want.
private static StringBuilder sb;

private static List<String> read(String filename) throws IOException
{
    List<String> list = new ArrayList<String>;
    try (reader = new Scanner(new File(filename)))
    {
        while(reader.hasNext())
        { list.add(reader.nextLine()); }
    } catch (...) {...}//catch errors...
}

//I'm going to build the whole file in one string, but you could also have this method return one line at a time (something like an iterator) and output it to the file to avoid creating the massive string
private static String interleave(List<String> one, List<String> two, List<String> three)
{
    sb = new StringBuilder();
    for (int i = 0; i < one.size(); i++)//notice no checking on size equality of words or the lists. you might want this
    {
        sb.append(one.get(i)).append(two.get(i)).append(three.get(i)).append("\n");
    }
    return sb.toString()
}

Obviously there is still some to be desired in terms of memory and performance; additionally there are ways to make this slightly more extensible to other situations, but it's a good starting point. With c#, I could more easily make use of the iterator to make interleave give you one line at a time, potentially saving memory. Just a different idea!

D. Ben Knoble
  • 4,273
  • 1
  • 20
  • 38
  • Your approach is definitely interesting, although if I went with an array I would think that it would be better to create the array in the method that generates the numbers first. I'll write something up and post that approach soon. – Elliander Jul 20 '15 at 03:15
  • 1
    That would be an interesting take on it. Avoid the extra files – D. Ben Knoble Jul 20 '15 at 03:27