0

I have an app in which I have to read a .txt file so that I can store some values and keep them. This is working pretty well, except for the fact that I want to make those values non-readable or "non-understandable" for external users.

My idea was to convert the file content into Hex or Binary and, in the reading process, change it back to Char. The thing is that I don't have access to methods such as String.Format due to my compiler.

Here's how I'm currently reading and keeping the values:

                byte[] buffer = new byte[1024];
                int len = myFile.read(buffer);
                String data = null;
                int i=0;
                data = new String(buffer,0,len);

Class to open and manipulate the file:

public class File {
    private boolean debug = false;
    private FileConnection fc = null;
    private OutputStream os = null;
    private InputStream is = null;
    private String fileName = "example.txt";
    private String pathName = "logs/";
    final String rootName = "file:///a:/";

    public File(String fileName, String pathName) {
        super();
        this.fileName = fileName;
        this.pathName = pathName;
        if (!pathName.endsWith("/")) {
            this.pathName += "/"; // add a slash
        }
    }


    public boolean isDebug() {
        return debug;
    }

    public void setDebug(boolean debug) {
        this.debug = debug;
    }


    public void write(String text) throws IOException {
        write(text.getBytes());
    }


    public void write(byte[] bytes) throws IOException {
        if (debug)
            System.out.println(new String(bytes));
        os.write(bytes);
    }


    private FileConnection getFileConnection() throws IOException {
        // check if subfolder exists
        fc = (FileConnection) Connector.open(rootName + pathName);
        if (!fc.exists() || !fc.isDirectory()) {
            fc.mkdir();
            if (debug)
                System.out.println("Dir created");
        }
        // open file
        fc = (FileConnection) Connector.open(rootName + pathName + fileName);
        if (!fc.exists())
            fc.create();
        return fc;
    }

    /**
     * release resources
     */
    public void close() {
        if (is != null)
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        is = null;
        if (os != null)
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        os = null;
        if (fc != null)
            try {
                fc.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        fc = null;

    }

    public void open(boolean writeAppend) throws IOException {
        fc = getFileConnection();
        if (!writeAppend)
            fc.truncate(0);
        is = fc.openInputStream();
        os = fc.openOutputStream(fc.fileSize());

    }

    public int read(byte[] buffer) throws IOException {

        return is.read(buffer);
    }

    public void delete() throws IOException {
        close();
        fc = (FileConnection) Connector.open(rootName + pathName + fileName);
        if (fc.exists())
                fc.delete();


    }

}

I would like to know a simple way on how to read this content. Binary or Hex, both would work for me.

halfer
  • 19,824
  • 17
  • 99
  • 186
Lkun
  • 3
  • 2
  • What compiler are you using that doesn't support String's format method? It's been around since Java 1.5... Would recommend updating your compiler, if that's an option. – Ironcache Nov 28 '16 at 15:22
  • It's not since I'm developing for a device that only works with 1.3, sadly. – Lkun Nov 28 '16 at 15:29
  • I certainly have no first-hand knowledge of how to do this then, but is [this question](http://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to-a-hex-string-in-java) helpful at all? – Ironcache Nov 28 '16 at 15:38
  • jdk 1.3 :o . Why don't you try BufferedReader and InputStreamReader ? – Tea Nov 28 '16 at 15:41
  • @tuyendev It could be a solution! How would you do it? – Lkun Nov 28 '16 at 15:46
  • This solution work with JDK 1.3, you can try here : https://www.mkyong.com/java/how-to-read-file-from-java-bufferedinputstream-example/ – Tea Nov 28 '16 at 16:22
  • This provides a clean method of reading String objects from the files, but note that the user is also looking to convert that String of user-readable data into a non-user readable format (which is the actual problem, as I understand it). @Lkun have you considered encrypting/decrypting the file? – Ironcache Nov 28 '16 at 16:36
  • Tuyendev, thanks I will give it a try! @Ironcache Yes I have! But since I need to make that encryption out of the program I don't know if it is the most simple way to solve this. But if I did choose to encrypt this, what type of encryption and how would you do it? Thanks once again to you both. – Lkun Nov 28 '16 at 16:57
  • If you're just trying to obfuscate the content (and storing in binary format is basic obfuscation in this sense) you could just do some char-char mapping to 'encrypt' the data before output and the opposite on the way back in? – JohnXF Nov 28 '16 at 18:06
  • Given that you're really just looking to obfuscate the data (not necessarily requiring high-fidelity encryption), I'd just use something extremely simple. You could take a look at [TEA](https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm), but even that might be overkill. could simply "salt" each of your `byte` values (IE: for each byte you output, add an amount, and, when reading it in, subtract that same amount). You could also setup byte-to-byte mapping, similar to what @JohnFergus proposed. – Ironcache Nov 28 '16 at 21:18
  • That's exactly what I was thinking about @Ironcache. The thing is I don't have a clue on how to compose my file with the byte values affected to non visible ASCII caracters. Also, a problem would be on how I would translate the information since I dont have access to String.format(). John Fergus, that could be a solution. Could you provide more concrete information? Sorry for the questions but I've never done something similar. EDIT: I've edited the question with the File class in which I open the file, etc. – Lkun Nov 29 '16 at 09:05
  • My thinking was to use a simple cipher where you match each possible character to a different (random) character. Only you know the mapping. So suppose your file will only contain possible characters [ABCD] then you could map them to [BADC] and when you want to write out A, you write out B, etc. Do the reverse on the way back in. Something like ROT13 or similar. See https://en.wikipedia.org/wiki/Substitution_cipher for examples. – JohnXF Nov 29 '16 at 09:44
  • @JohnFergus that solution would fit perfectly if the solution only envolved letters. I have IP's which I would like to hide aswell. Since ROT only works for letters I would rather use something else. But thanks for the suggestion! – Lkun Nov 29 '16 at 14:11
  • You can easily extend the concept to work for numbers. IE: `char[] plain = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.".toCharArray();` Then your encrypt function is simply a matter of finding the index of the character, shifting the index right/left by an amount (modulus size, of course). When you want to decrypt, just do the same process, but shift in the opposite direction. – Ironcache Nov 29 '16 at 15:09
  • I posted an answer outlining this. I realized that I was being foolish with this whole `plain` array thing, and you could just directly shift the `char`. Not sure if this has underflow/overflow issues. It shouldn't, as any time you overflow on ciphering you would then underflow by the same amount on deciphering. Anyway, hope it helps. – Ironcache Nov 29 '16 at 16:32

2 Answers2

1

So, with some understanding of the question, I believe you're really looking for a form of obfuscation? As mentioned in the comments, the easiest way to do this is likely a form of cipher.

Consider this example implementation of a shift cipher:

Common

int shift = 11;

Writing

// Get the data to be wrote to file.
String data = ...

// cipher the data.
char[] chars = data.toCharArray();
for (int i = 0; i < chars.length; ++i) {
    chars[i] = (char)(chars[i] + shift);
}
String cipher = new String(chars);

// Write the data to the cipher file.
...

Reading

// Read the cipher file.
String data = ...

// Decipher the data.
char[] chars = data.toCharArray();
for (int i = 0; i < chars.length; ++i) {
    chars[i] = (char)(chars[i] - shift);
}
String decipher = new String(chars);

// Use data as required.
...

Here's an example implementation on Ideone. The output:

Data    : I can read this IP 192.168.0.1
Cipher  : T+nly+}plo+st~+T[+<D=9<AC9;9<
Decipher: I can read this IP 192.168.0.1

I tried to keep this as low level as possible in order to satisfy the Java 3 requirement.

Note that this is NOT secure by any means. Shift ciphers (like most ciphers in a bubble) are trivial to break by malicious entities. Please do not use this if security is an actual concern.

Ironcache
  • 1,719
  • 21
  • 33
0

Your solution is too complex. With java 8, you can try :

    String fileName = "configFile.txt";

    try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
        //TO-DO .Ex
        stream.forEach(System.out::println);

    } catch (IOException e) {
        e.printStackTrace();
    }
Tea
  • 873
  • 2
  • 7
  • 25
  • User specified that their compiler doesn't support String's format method... it certainly doesn't support streams. – Ironcache Nov 28 '16 at 15:37
  • @tuyendev, as Ironcache mentioned i'm limited to 1.3ide. Thanks in advance. – Lkun Nov 28 '16 at 15:47