3

I'm trying to print a very large BigInteger to a .txt file, but when the number reaches a certain size, it prints nothing. Code:

BigInteger bi = new BigInteger("16777216");
int exponent = 1000000;
bi = bi.pow(exponent);

String txtToPrint = bi.toString();
sendToFile(txtToPrint, "output.txt");

private static void sendToFile(String txtToPrint, String fileName) {

        try {

            FileWriter fileWriter = new FileWriter(fileName);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
            bufferedWriter.write(txtToPrint);

            bufferedWriter.close();
        }
        catch(IOException e) {
            System.out.println("Error writing to file '" + fileName + "'");
        }

}

Whenever the exponent is greater than 566 the output file is empty, instead of containing the number. The goal is to have an exponent of 1 000 000, or even greater.

I thought BigInteger did not have a size limit, so my question is: What limit am I exceeding and is there a way to solve this problem?

EDIT: When trying to flush and close the filewriter, I got this exception:

java.io.IOException: Stream closed
at sun.nio.cs.StreamEncoder.ensureOpen(Unknown Source)
at sun.nio.cs.StreamEncoder.flush(Unknown Source)
at java.io.OutputStreamWriter.flush(Unknown Source)
at PrintInt.main(PrintInt.java:4

EDIT: The problem only occurs when running the program in Eclipse, I tried exporting it to an external jar, and everything worked just fine. I am using Eclipse Mars.1 Release (4.5.1) and Java jre1.8.0_131 and Cp1252 encoding.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Rudy
  • 437
  • 2
  • 7
  • FYI: _I thought BigInteger did not have a size limit_ there are limit to the size of an array, so `Integer.MAX_VALUE` (minus some value) digits. But with that exponent, you should be OK... – AxelH Nov 17 '17 at 11:45
  • I did test your code and my file is correct.7056KB... – AxelH Nov 17 '17 at 11:56
  • @AxelH Do you have any idea why it is working for you, and not for me? – Rudy Nov 17 '17 at 12:02
  • I am pointing the `BufferWriter` here ... – AxelH Nov 17 '17 at 12:02

4 Answers4

2

I am mostly guessing here. I would guess the problem come from the BufferWriter.

Let's try with a more direct approch, Outputstream and try with resource to close everything properly.

File f = new File(fileName);
try (
        FileOutputStream fos = new FileOutputStream(f);
        OutputStreamWriter os = new OutputStreamWriter(fos);
        Writer out = new BufferedWriter(os) 
){
    out.write(txtToPrint);
} catch(IOException e) {
    System.out.println("Error writing to file '" + fileName + "'");
}

I have seen it in the past some OS synchronization issues but the file never loose the data, the data is just copied with a small delayed... but why not ... after the write, just wait for the OS to validate the data is flush in the file (not in the OS cache)

out.flush(); //flush the stream
fos.getFD().sync(); //sync with the OS
AxelH
  • 14,325
  • 2
  • 25
  • 55
  • Thank you. I did try this, and the result was the same, unfortunately. Moreover, I am also unable to print the output to console. – Rudy Nov 17 '17 at 12:15
  • @Rudy, for the console, see [eclipse limitation](https://stackoverflow.com/questions/34535561/not-able-to-print-very-large-strings-in-java-neither-in-eclipse-nor-in-cmd), probably not the only IDE doing so ;) – AxelH Nov 17 '17 at 12:17
  • That makes sense, however the number stops printing to console and output at the same exponent (567) – Rudy Nov 17 '17 at 12:21
  • Tried the second approach, using Outputstream instead, still did not print. – Rudy Nov 17 '17 at 12:26
  • @Rudy You used the same syntax ? Because you need to `close` everything to be sure it is flushed. Using the `try-with-resource` assure that. – AxelH Nov 17 '17 at 12:27
  • Yes, I did use the same syntax. – Rudy Nov 17 '17 at 12:32
  • I am out of option/idea ... last think I can say is that it could be stuck in the cache of the OS ... seen it in a multi OS envionnement. Using `fos.getFD().sync()` to wait the the OS dump the cached data into the file. But this will not matter here... This is my last edit, I can only guess since I can't reproduce this ... edit your question with the Java version. VM configuration, OS, .. – AxelH Nov 17 '17 at 12:37
  • Thank you for the help though. Forgot to mention that trying to flush/close the filewriter threw an IOException. – Rudy Nov 17 '17 at 12:40
  • @Rudy You did forgot... what exception, add the stack trace in your question with a [edit]... this is not a detail ;) – AxelH Nov 17 '17 at 12:41
1

In Java 8, some information was added to the BigInteger javadoc, giving a minimum supported range and the actual limit of the current implementation:

BigInteger must support values in the range -2Integer.MAX_VALUE (exclusive) to +2Integer.MAX_VALUE (exclusive) and may support values outside of that range.

Implementation note: BigInteger constructors and operations throw ArithmeticException when the result is out of the supported range of -2Integer.MAX_VALUE (exclusive) to +2Integer.MAX_VALUE (exclusive).

G2M
  • 68
  • 1
  • 6
  • True but that's not the problem here, the value here is not that big. The `BigInteger` is correctly calculated – AxelH Nov 17 '17 at 11:53
  • 1
    Thank you for the reply. Would the thrown exception be printed though? No errors were printed when I ran the program. – Rudy Nov 17 '17 at 11:58
  • @Rudy My thought would be that maybe the actual String size is the issue. Someone mentioned it right below but is there a chance 1/2 your heap size is not enough to hold all the characters at 2 byte per? If thats the limiting factor there would be no exception and no output I suppose. – G2M Nov 17 '17 at 12:03
  • The string "only" have a length of 7224720 character. You still have some space. Heap space could be, but it would throw an Error ... – AxelH Nov 17 '17 at 12:06
  • @G2M I would think that heap size might be the issue then, because the problem occurs with an exponent as low as 600. – Rudy Nov 17 '17 at 12:10
0

I would say, the String size is maybe the limit.

You should be able to get a String of length Integer.MAX_VALUE (always 2147483647 (231 - 1) by the Java specification, the maximum size of an array, which the String class uses for internal storage) or half your maximum heap size (since each character is two bytes), whichever is smaller.

h_matze_h
  • 98
  • 1
  • 9
0

Yes its used when we need very big numbers with arbitrary precision. It's important to note that "arbitrary" precision or number of digits does not mean "unlimited": it means that the number of digits in a number or number of digits of precision in a calculation is limited by memory and/or defined limits to precision that we specify.