I am trying to decode the data encoded in the image. The encoding works fine and the data size of image also changes but for some reason the decoded data is an empty string. Either the encoded data get lost or this code has some mistake.
int temp,tempText=0,x=0,p=0;
try
{
image= ImageIO.read(new File("C:\\Users\\Desktop\\Encoded.png"));
}
catch (IOException e)
{
e.printStackTrace();
}
for(int i=0;i<image.getWidth();i++)
{
for(int j=0;j<image.getHeight();j++)
{
pixels[i][j]=image.getRGB(i, j);
}
}
for(int i=0;i<Width;i++)
{
for(int j=0;j<Height;j++)
{
temp=pixels[i][j];
int change=0;
for(int k=0;k<4;k++) // 4 iterations for 4bytes of every pixel
{
if(k==0)
{
change=1;
}
else
if(k==1)
{
change=256;
}
else
if(k==2)
{
change=65536;
}
else
if(k==3)
{
change = 16777216;
}
tempText=tempText | (pixels[i][j] & change);
p++;
if(p==8) // because character is of 8bits
{
myString.concat(String.valueOf(tempText));// Writing decoded data in string
p=0;
tempText=0;
}
}
}
// Writing in file
try
{
file = new File("C:\\Users\\Desktop\\Retreive.txt");
fw = new FileWriter(file);
bw= new BufferedWriter(fw);
bw.write(myString);
bw.close();
}
catch (Exception e)
{
e.printStackTrace();
}
Kindly notify me if any mistake I am making or any thing this code is lacking.
String.concat doesn't change the string you call it on, but instead returns a new string. So if you use myString = myString.concat(...) instead, you might get better results. If tempText contains a character code, you could cast it to a char (since String.valueOf returns the string representation of the int):
// Writing decoded data in string
// myString = myString.concat(String.valueOf(tempText));
myString += (char) tempText;
instead of:
myString.concat(String.valueOf(tempText));// Writing decoded data in string
Related
This code below is part of a program, that will find the number of occurrences of the input character in a text file
public static void main(String[] args){
[...]
java.io.File file1=new java.io.File(dirPath1);
FileInputStream fis = new FileInputStream(file1);
System.out.println(" return "+rec(sc.next().charAt(0),fis));
}
public static int rec (char ch, FileInputStream fis)throws IOException{
char current=0;
if(fis.available()==0){
return 0;
}
if(fis.read()!=-1){
current = (char) fis.read();
}
if(current==ch) {
return 1+rec(ch,fis);
}else
return rec(ch,fis);
}
}
The problem is:
If the file has one character, and ch=that one character. it returns 0, when I traced the code I found that it doesn't enter if(current==ch). Although, they are the same char.
if there is more than on character,strings some of them-the matches chars- will enter if block and others won't.
How can I fix this ?
Is there another way to find the number of occurrences recursively ?
another question: should I use try and catch in rec method to catch IOException ?
Thanks in advance
P.S. this program is from assignment,I have to use recursion and compare it with iteration.
you call fis.read() twice first one read first character and second one read nothing
this is your answer
public static int rec(char ch, FileInputStream fis) throws IOException {
char current = 0;
if (fis.available() == 0) {
return 0;
}
int read = fis.read();
if (read != -1) {
current = (char) read;
}
if (current == ch) {
return 1 + rec(ch, fis);
}
else
return rec(ch, fis);
}
My suggestion would be as follows:
Read the whole text file into a java.lang.String
Then use the library Apache Commons Lang and use this method for counting the occurrences:
http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#countMatches-java.lang.CharSequence-java.lang.CharSequence-
You should use FileReader to read chars from text file.
Reader reader = new FileReader("MyFile.txt");
I think using while ((i=reader.read()) != -1) is a better approach instead of three if and an else.
So you can achieve this with fewer lines of code:
public static int rec (char ch, Reader reader)throws IOException{
char current=0;
int i;
while ((i=reader.read()) != -1) {
current = (char) i;
if(current==ch) {
return 1+rec(ch,reader);
}else
return rec(ch,reader);
}
return 0;
}
I think there is no need to use try and catch in rec method to catch IOException. I have used it here:
try {
Reader reader = new FileReader("MyFile.txt");
System.out.println(" return " + rec('a', reader));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Below is my code. I am converting images into bytearray values.
Here finalPathNames.size() == 4
So i want to save the byteArray values eachtime like byteArray1,byteArray2,byteArray3,byteArray4 which is inside for loop
Set<String> finalPathNames = sharedpre.getStringSet("prePathNames", null);
InputStream is = null;
for (String temp : finalPathNames) {
try {
is = new FileInputStream(temp);
try {
byteArray = streamToBytes(is);
} finally {
is.close();
}
} catch (Exception e) {
}
}
is there any optimized way to find result values
Send the bytes to the server, when you retrieve them or keep them in a list (in case you need them more than 1 time)
// as mentioned in the comments, user wants specifically 4 arrays
byte[][] byteArrays = byte[4][]; //
Set<String> finalPathNames = sharedpre.getStringSet("prePathNames", null);
InputStream is = null;
int index = 0;
for (String temp : finalPathNames) {
byteArrays[index] = new byte[0]; // in case of exception clear array. possibly set to null
try {
is = new FileInputStream(temp);
try {
byte[] byteArray = streamToBytes(is);
byteArrays[index] = byteArray;
} finally {
is.close();
}
} catch (Exception e) {
}
finally {
index++;
}
}
Then the resulting streams are available as:
byteArrays[0], byteArrays[1], byteArrays[2], byteArrays[3],
So I use the following methods
(File is converted to Byte Array through 'convertFileToByteArray()', then written to .txt file by 'convertByteArrayToBitTextFile()'
to convert any kind of file into a Binary Text file (and by that I mean only 1's and 0's in human readable form.)
public static byte[] convertFileToByteArray(String path) throws IOException
{
File file = new File(path);
byte[] fileData;
fileData = new byte[(int)file.length()];
FileInputStream in = new FileInputStream(file);
in.read(fileData);
in.close();
return fileData;
}
public static boolean convertByteArrayToBitTextFile(String path, byte[] bytes)
{
String content = convertByteArrayToBitString(bytes);
try
{
PrintWriter out = new PrintWriter(path);
out.println(content);
out.close();
return true;
}
catch (FileNotFoundException e)
{
return false;
}
}
public static String convertByteArrayToBitString(byte[] bytes)
{
String content = "";
for (int i = 0; i < bytes.length; i++)
{
content += String.format("%8s", Integer.toBinaryString(bytes[i] & 0xFF)).replace(' ', '0');
}
return content;
}
Edit: Additional Code:
public static byte[] convertFileToByteArray(String path) throws IOException
{
File file = new File(path);
byte[] fileData;
fileData = new byte[(int)file.length()];
FileInputStream in = new FileInputStream(file);
in.read(fileData);
in.close();
return fileData;
}
public static boolean convertByteArrayToBitTextFile(String path, byte[] bytes)
{
try
{
PrintWriter out = new PrintWriter(path);
for (int i = 0; i < bytes.length; i++)
{
out.print(String.format("%8s", Integer.toBinaryString(bytes[i] & 0xFF)).replace(' ', '0'));
}
out.close();
return true;
}
catch (FileNotFoundException e)
{
return false;
}
}
public static boolean convertByteArrayToByteTextFile(String path, byte[] bytes)
{
try
{
PrintWriter out = new PrintWriter(path);
for(int i = 0; i < bytes.length; i++)
{
out.print(bytes[i]);
}
out.close();
return true;
}
catch (FileNotFoundException e)
{
return false;
}
}
public static boolean convertByteArrayToRegularFile(String path, byte[] bytes)
{
try
{
PrintWriter out = new PrintWriter(path);
for(int i = 0; i < bytes.length; i++)
{
out.write(bytes[i]);
}
out.close();
return true;
}
catch (FileNotFoundException e)
{
return false;
}
}
public static boolean convertBitFileToByteTextFile(String path)
{
try
{
byte[] b = convertFileToByteArray(path);
convertByteArrayToByteTextFile(path, b);
return true;
}
catch (IOException e)
{
return false;
}
}
I do this to try methods of compression on a very fundamental level, so please let's not discuss why use human-readable form.
Now this works quite well so far, however I got two problems.
1)
It takes foreeeever (>20 Minutes for 230KB into binary text). Is this just a by-product of the relatively complicated conversion or are there other methods to do this faster?
2) and main problem:
I have no idea how to convert the files back to what they used to be. Renaming from .txt to .exe does not work (not too surprising as the resulting file is two times larger than the original)
Is this still possible or did I lose Information about what the file is supposed to represent by converting it to a human-readable text file?
If so, do you know any alternative that prevents this?
Any help is appreciated.
The thing that'll cost you most time is the construction of an ever increasing String. A better approach would be to write the data as soon as you have it.
The other problem is very easy. You know that every sequence of eight characters ('0' or '1') was made from a byte. Hence, you know the values of each character in an 8-character block:
01001010
^----- 0*1
^------ 1*2
^------- 0*4
^-------- 1*8
^--------- 0*16
^---------- 0*32
^----------- 1*64
^------------ 0*128
-----
64+8+2 = 74
You only need to add the values where an '1' is present.
You can do it in Java like this, without even knowing the individual bit values:
String sbyte = "01001010";
int bytevalue = 0;
for (i=0; i<8; i++) {
bytevalue *= 2; // shifts the bit pattern to the left 1 position
if (sbyte.charAt(i) == '1') bytevalue += 1;
}
Use StringBuilder to avoid generating enormous numbers of unused String instances.
Better yet, write directly to the PrintWriter instead of building it in-memory at all.
Loop through every 8-character subsequence and call Byte.parseByte(text, 2) to parse it back to a byte.
In Java, here is the code to read a file with a table of integers:
public static int[][] getDataset() {
// open data file to read n and m size parameters
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(filePath));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
// count the number of lines
int i = -1;
String line = null, firstLine = null;
do {
// read line
try {
line = br.readLine();
i++;
if (i == 0) firstLine = line;
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
} while (line != null);
// close data file
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
// check the data for emptiness
if (i == 0) {
System.out.println("The dataset is empty!");
System.exit(1);
}
// initialize n and m (at least the first line exists)
n = i; m = firstLine.split(" ").length;
firstLine = null;
// open data file to read the dataset
br = null;
try {
br = new BufferedReader(new FileReader(filePath));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
// initialize dataset
int[][] X = new int[n][m];
// process data
i = -1;
while (true) {
// read line
try {
line = br.readLine();
i++;
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
// exit point
if (line == null) break;
// convert a line (string of integers) into a dataset row
String[] stringList = line.split(" ");
for (int j = 0; j < m; j++) {
X[i][j] = Integer.parseInt(stringList[j]);
}
}
// close data file
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
return X;
}
Dataset size parameters n and m are of type static final int and declared outside as well as static final String filePath.
I give you my solution (maybe will be useful for newbies later coming to read this) and ask if it is possible to make it faster in time and/or consuming less memory? I'm interested in perfect micro-optimization, any advice would be great here. In particular I do not like the way the file is opened twice.
Read the file only once and add all lines to an ArraList<String>.
ArrayList grows automatically.
Later process that ArrayList to split the lines.
Further optimisations:
Strimg.split uses a huge regular expression analyzer. Try it with StringTokenizer or your own stringsplit method.
Instead of ArrayList you could avoid overhead by using GrowingIntArray,or GrowingStringArray, these avoid some overhead but are less handy.
speed and mempory usage are contradicting, often you cannot optimize both.
You can save memor by using a one dimesnional array, in java 2d arrays need more space becauseeach column is an object.
access one dim array by X[col + row *rowsize].
Actually I had a .rtf file and from that I was trying to create a csv file. While searching I saw that I have convert it into plain text and then to csv file. But right now I am kind of stuck with logic. I am not getting idea what to apply to move forward.
I have below data which I want to convert to csv.
Input :
Search Target Redmond40_MAS Log Written 01/18/2013 9:13:19 Number of attempts 1
Search Target Redmond41_MAS Log Written 01/19/2013 9:15:16 Number of attempts 0
Output :
Search Target,Log Written,Number of attempts
Redmond40_MAS,01/18/2013 9:13:19,1
Redmond41_MAS,01/19/2013 9:15:16,0
If there was any delimiter then I would have done it but in this case I know are the "keys" i.e. header values but not getting the idea how to extract corresponding contents.
Any suggestion will help.
import java.io.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.rtf.RTFEditorKit;
public class Rtf2Csv {
public static void main(String[] args) {
RTFEditorKit rtf = new RTFEditorKit();
Document document = rtf.createDefaultDocument();
try {
FileInputStream fi = new FileInputStream("test.rtf");
rtf.read(fi, document, 0);
} catch (FileNotFoundException e) {
System.out.println("File not found");
} catch (IOException e) {
System.out.println("I/O error");
} catch (BadLocationException e) {
}
String output = "Search Target,Log Written,Number of attempts";
try {
String text = document.getText(0, document.getLength());
text = text.replace('\n', ' ').trim();
String[] textHeaders = text
.split("===================================================================================");
String[] header = { "Search Target", "Log Written",
"Number of attempts"};
System.out.println(textHeaders.length);
int headLen = header.length;
int textLen = textHeaders.length;
for (int i = 0; i < textLen; i++) {
String finalString = "";
String partString = textHeaders[i];
for (int j = 0; j < headLen; j++) {
int len = header[j].length();
if (j + 1 < header.length)
finalString += partString.substring(
partString.indexOf(header[j]) + len,
partString.indexOf(header[j + 1])).trim()
+ ",";
else
finalString += partString.substring(
partString.indexOf(header[j]) + len).trim();
}
output += "\n" + finalString;
}
} catch (BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
FileWriter writer = new FileWriter("output.csv");
writer.append(output);
writer.flush();
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I have written this code. Is there any better way to improve it?
If you are sure it is fixed width, then just calculate the length of the fields. Otherwise, I would recommend writing a simple parser. You might get lucky with the correct regular expression, but from my experience this can be a lot of trail and error.
It should not be too hard to parse it...
I would suggest using Scanner or StringTokenizer. There is an in depth explanation here:
Scanner vs. StringTokenizer vs. String.Split
Something like this should do it:
StringTokenizer s = new StringTokenizer("Search Target Redmond40_MAS Log Written 01/18/2013 9:13:19 Number of attempts 1"
);
String out = new String();
while (s.hasMoreTokens()) {
out = s.nextToken() + "," + out ;
}
If the columns you are interested in are of a fixed width, you may open the txt file in Excel and place column dividers where desired.
It would be simple to export from Excel as a csv.
If you want to read it in line by line you can use something like this:
public int countLines(File inFile)
{
int count = 0;
Scanner fileScanner = new Scanner(inFile);
while(fileScanner.hasNextLine()) //if you are trying to count lines
{ //you should use hasNextLine()
fileScanner.nextLine() //advance the inputstream
count++;
}
return count;
}
Does this answer your question?