How do I copy an array? - java

What I'm trying to do is I'm trying to take an image and make it a tiled image. The starting image should look like this.
http://i1146.photobucket.com/albums/o525/walroid/letter_Q_grayscale_zpsd3b567a7.jpg
And then what the image is turned into tiles then it should look like this:
http://i1146.photobucket.com/albums/o525/walroid/replicate_example_zps5e5248e8.jpg
In my code the pictures are saved into an array which is called into the method. What I want to do is copy that array and then put it into another array which will replicate the image. How do I do that?
Here's my entire code:
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
public class ImageProcessor {
public static void main(String[] args) {
if (args.length < 3) {
System.out.println("Not enough arguments");
System.exit(-1);
}
String function = args[0];
if (function.equals("-reflectV")) {
String inputFileName = args[1];
String outputFileName = args[2];
int[][] imageArr = readGrayscaleImage(inputFileName);
int[][] reflectedArr = reflectV(imageArr);
writeGrayscaleImage(outputFileName, reflectedArr);
} else if (function.equals("-reflectH")) {
String inputFileName = args[1];
String outputFileName = args[2];
int[][] imageArr = readGrayscaleImage(inputFileName);
int[][] reflectedArr = reflectH(imageArr);
writeGrayscaleImage(outputFileName, reflectedArr);
} else if (function.equals("-ascii")) {
String inputFileName = args[1];
String outputFileName = args[2];
int[][] imageArr = readGrayscaleImage(inputFileName);
int[][] reflectedArr = reflectV(imageArr);
try {
PrintStream output = new PrintStream(new File("output.txt"));
} catch (java.io.FileNotFoundException ex) {
System.out.println("Error: File Not Found");
System.exit(-1);
}
} else if (function.equals("-adjustBrightness")) {
String amount = args[1];
int a = Integer.parseInt(amount);
System.out.print(a)
String inputFileName = args[1];
String outputFileName = args[2];
int[][] imageArr = readGrayscaleImage(inputFileName);
int[][] brightnessArr = adjustBrightness(imageArr);
writeGrayscaleImage(outputFileName, brightnessArr);
} else
System.out.println("That is not a valid choice");
system.exit(-1)
public static int[][] reflectV ( int[][] arr){
int[][] reflected = new int[arr.length][arr[0].length];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
reflected[i][j] = arr[i][arr[i].length - 1 - j];
}
}
return reflected;
}
public static int[][] reflectH ( int[][] arr){
int[][] reflected = new int[arr.length][arr[0].length];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
reflected[j][i] = arr[i][arr[j].length - 1 - j];
}
}
return reflected;
}
public static int[][] adjustBrightness ( int[][] arr){
int[][] brightness = new int[arr.length][arr[0].length];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
RGB
}
}
return brightness;
}
public static int[][] readGrayscaleImage (String filename){
int[][] result = null; //create the array
try {
File imageFile = new File(filename); //create the file
BufferedImage image = ImageIO.read(imageFile);
int height = image.getHeight();
int width = image.getWidth();
result = new int[height][width]; //read each pixel value
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int rgb = image.getRGB(x, y);
result[y][x] = rgb & 0xff;
}
}
} catch (IOException ioe) {
System.err.println("Problems reading file named " + filename);
System.exit(-1);
}
return result;
}
public static void writeGrayscaleImage(String filename, int[][] array) {
int width = array[0].length;
int height = array.length;
try {
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB); //create the image
//set all its pixel values based on values in the input array
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int rgb = array[y][x];
rgb |= rgb << 8;
rgb |= rgb << 16;
image.setRGB(x, y, rgb);
}
}
//write the image to a file
File imageFile = new File(filename);
ImageIO.write(image, "jpg", imageFile);
} catch (IOException ioe) {
System.err.println("Problems writing file named " + filename);
System.exit(-1);
}
}
}

You need to do a "deep copy" of the array. Simply copying your array to a new variable will only assign the reference (shallow copy), and if you manipulate data in one of the arrays, it will change both.
Shallow Copy:
String[] myArray2 = myArray1;
This will essentially have 2 references pointing at the same data. If you change anything in myArray2, it will also change in myArray1.
Deep Copy:
There are multiple ways to do a deep copy. The obvious way is to iterate over your array and copy each element one at a time into the new array.
String[] myArray2 = new String[myArray1.length];
for (int i = 0; i < myArray1.length; i++) {
myArray2[i] = myArray1[i];
}
A sometimes simpler/faster way is to serialize your array and then de-serialize it while it's still in memory. This causes the JVM to treat the de-serialized array as an entirely new array ("no strings attached" so-to-speak).
Here's an example from an old project of mine:
/**
* Clones an object creating a brand new
* object by value of input object. Accomplishes this
* by serializing the object, then deservializing it.
*
* #param obj Input Object to clone
* #return a new List<Product> type cloned from original.
* #throws IOException If IOException
* #throws ClassNotFoundException If ClassNotFoundException
*/
private static List<Product> cloneProdList(Object obj) throws IOException, ClassNotFoundException {
java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
java.io.ObjectOutputStream obj_out = new java.io.ObjectOutputStream(bos);
obj_out.writeObject(obj);
java.io.ByteArrayInputStream bis = new java.io.ByteArrayInputStream(bos.toByteArray());
java.io.ObjectInputStream obj_in = new java.io.ObjectInputStream(bis);
#SuppressWarnings("unchecked")
List<Product> newObj = (List<Product>)obj_in.readObject();
bos.close();
bis.close();
obj_out.close();
obj_in.close();
return newObj;
}
This code takes a List type as the input (well, it actually casts to an Object type), serializes and then de-serializes while still in memory, then casts back into a List object and returns the new object back out of the method.
You can modify it to use an Array object instead pretty easily. (an array[] type will autobox into Array for you)

https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#arraycopy%28java.lang.Object,%20int,%20java.lang.Object,%20int,%20int%29
You can use System.arraycopy in a for loop to copy from one array to other.

Using the Array class and calling the static method Array.copyOf(array, array.length) is quite handy so that if myArray1 is the previous array and myArray2 is the new array then myArray2 = Array.copyOf(myArray1, myArray1.length)

Related

CSV Handling / FileReader and BufferedReader with UTF-8

I am having issues with reading a csv file and UTF-8. What I am doing is, reading the file to a String Array. Converting the String Array to a 2D String Array, depending on the line separator. Cleaning the line separator and displaying the 2D String Array in the console.
The issue is, that special characters like ö and ä are messed up on the console.
System.out.println("Default Charset=" + Charset.defaultCharset());
Tells me that my system is using UTF-8. What am I doing wrong?
I´m handling the CSV files with a 2D Array to get direct access to the rows and columns. Is there a better approach for that?
// Reading File
public static String[] readFile(String path) throws IOException {
FileReader input = new FileReader(path);
BufferedReader br = new BufferedReader(input);
String[] stringBuff = new String[countLines(path)];
int lines = countLines(path);
for (int j = 0; j < lines; j++) {
stringBuff[j] = br.readLine();
}
br.close();
return stringBuff;
}
// Converting to a 2D Array
public static String[][] convert(String[] array, String path) throws IOException {
int lines = countLines(path);
int[] locationarray;
int columns = (findcolumn(array)) + 1;
String[][] array2 = new String[lines][columns];
for (int i = 0; i < array.length; i++) {
locationarray = findlocation(array, i);
for (int j = 0; j < columns; j++) {
array2[i][j] = array[i].substring(locationarray[j], locationarray[j + 1]);
array2[i][j] = cleanup(array2[i][j]);
// System.out.print(array2[i][j]);
}
// System.out.println();
}
return array2;
}
// Show Array
public static void showarray(String[][] srcfinal) {
for (int i = 0; i < srcfinal.length; i++) {
for (int j = 0; j < srcfinal[i].length; j++) {
System.out.print(srcfinal[i][j]);
}
System.out.println();
}
}

Reading a text file into a char[][] array in Java

I am trying to fill a char[][] array from a text file and I cannot seem to figure out how to do it. I've tried to use .toCharArray() but it doesn't seem to work. If you can give any insight on how to make this work that would be awesome!
String filename = "ArrayHW2.txt";
int numTests = 6;
char[][] testAnswers = new char[50][5];
char[] key = new char[4];
Scanner input = null;
try
{
input = new Scanner(new File(filename));
}
catch(FileNotFoundException e)
{
System.out.println("Error Opening File");
System.exit(1);
}
for(int row = 0; row < testAnswers.length; row++)
{
for(int col = 0; col < testAnswers[row].length; col++)
{
testAnswers[row][col] = input.next().toCharArray();
}
}
input.close();
The basic problem is that you are trying to assign a character array to something was meant to hold a character. You might think of char[] type as storing the location in memory where characters are recorded, and a char type as the character itself.
When you call toCharArray() on a String, the return type is char[]. It looks like you expect this array to have a single character, like the A, B, C, or D of a multiple-choice test. You could get the first (and only?) character of that array with something like ...toCharArray()[0], but this is wasteful because a new array is created, and characters are copied into it from the source string. It's simpler to use the getCharAt() method on the String directly.
String filename = "ArrayHW2.txt";
char[][] testAnswers = new char[50][5];
try (Scanner input = new Scanner(Paths.get(filename))) {
for(int row = 0; row < testAnswers.length; row++) {
for(int col = 0; col < testAnswers[row].length; col++) {
String token = r.next();
if (token.length() != 1)
throw new IllegalArgumentException("Answers must be one character");
testAnswers[row][col] = token.charAt(0);
}
}
} catch (IOException ex) {
System.err.println("Error reading file: " + ex.getMessage());
System.exit(1);
}
String filename = "ArrayHW2.txt";
int numTests = 6;
char[][] testAnswers = new char[50][5];
//char[] key = new char[4];
Scanner input = null;
try
{
input = new Scanner(new File(filename));
}
catch(FileNotFoundException e)
{
System.out.println("Error Opening File");
System.exit(1);
}
int counter = 0;
while(scanner.hasNext())
{
copyString(testAnswers[counter], scanner.nextLine());
}
input.close();
its been a while i haven't code in java and im not sure about the methods but consider it a pseudo code .
you can use this copy :
void copyString(char[] arr, String x)
{
int size = x.length();
for (int i=0; i<size; i++){
arr[i] = x.CharAt(i);
}

Using readObject to get byte[][] giving OptionalDataException

I have a slight problem reading some files I have made. I am making a game and have decided to make my own file type for the maps. I have made a special application to make these map files. Once I instantiate a map I can choose to call readFile(String path) to set the map as the one saved. I know that I have to read and write the stream in the same order and everything went well until I added the statements about reading and writing the byte[][]. I cannot figure out why I am getting this exception and how to still read a byte[][]. Here is my class.
public class Map implements Serializable{
String savePath;
int boxWidth;
int boxHeight;
int mapWidth;
int mapHeight;
BufferedImage map;
byte[][] encoded;
LinkedList<BufferedImage> tileSet = new LinkedList<BufferedImage>();
Map(int boxWidth, int boxHeight, int mapWidth, int mapHeight){
map = new BufferedImage(boxWidth * mapWidth, boxHeight * mapHeight, BufferedImage.TYPE_INT_RGB);
Graphics g = map.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, map.getWidth(), map.getHeight());
g.dispose();
this.boxHeight = boxHeight;
this.boxWidth = boxWidth;
this.mapHeight = mapHeight;
this.mapWidth = mapWidth;
initEncode();
}
Map(){
map = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
this.boxHeight = 0;
this.boxWidth = 0;
this.mapHeight = 0;
this.mapWidth = 0;
initEncode();
}
void initEncode(){
int width = 2 * mapWidth + 1;
int height = 2 * mapHeight + 1;
encoded = new byte[width][height];
for(int i = 0; i < width; i++){
for(int j = 0; j < height; j++){
encoded[i][j] = 0;
}
}
}
void setMapTile(int i, int j, byte index){
encoded[2 * i + 1][2 * j + 1] = index;
}
void setMapWall(int i, int j, byte index){
encoded[2 * i][2 * i] = index;
}
void addToTileset(Tile tile){
tileSet.add(tile.tile);
writeFile(savePath);
}
//writing to file with path - boolean is for whether it went successfully or not
boolean writeFile(String path){
savePath = path;
try{
OutputStream file = new FileOutputStream(path);
OutputStream buffer = new BufferedOutputStream(file);
ObjectOutputStream output = new ObjectOutputStream(buffer);
writeObject(output);
output.close();
buffer.close();
file.close();
}catch(IOException ex){
System.err.println("Could not Write to file: " + path + "\nError caused by: " + ex);
return false;
}
return true;
}
//reading from file with path - boolean is for whether it went successfully or not
boolean readFile(String path){
savePath = path;
try{
InputStream file = new FileInputStream(path);
InputStream buffer = new BufferedInputStream(file);
ObjectInputStream in = new ObjectInputStream(buffer);
readObject(in);
initEncode();
file.close();
buffer.close();
in.close();
}catch(IOException ex){
System.err.println("Could not read from file: " + path + "\nError caused by: " + ex + "\n");
ex.printStackTrace();
return false;
}catch(ClassNotFoundException e){
System.err.println("Could not read from file: " + path + "\nError caused by: " + e + "\n");
e.printStackTrace();
}
return true;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeInt(boxHeight);
out.writeInt(boxWidth);
out.writeInt(mapHeight);
out.writeInt(mapWidth);
ImageIO.write(map, "png", out);
out.writeObject(encoded);
out.writeInt(tileSet.size());
for(BufferedImage b: tileSet){
ImageIO.write(b, "png", out);
}
}
public void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
boxHeight = in.readInt();
boxWidth = in.readInt();
mapHeight = in.readInt();
mapWidth = in.readInt();
map = ImageIO.read(in);
encoded = (byte[][]) in.readObject();
int tileSetSize = in.readInt();
for(int i = 0; i < tileSetSize; i++){
tileSet.add(ImageIO.read(in));
}
}
}
Is there some reason that my (byte[][]) readObject() line is throwing OptionalDataException and how do i still read/write my byte[][].
EDIT: Thank you for your answer Abhinav Kumar. I overlooked that but when I fixed the code it still gave me the same error on the same line. (The class has been fixed now).
You have to read the InputStream in the same order and same format which you write in the stream otherwise you would get OptionalDataException
You have written the data in OutputStream in the order :-
ImageIO.write(map, "png", out);
out.writeInt(2 * mapWidth + 1);
out.writeObject(encoded);
And you are reading the stream in the order :-
map = ImageIO.read(in);
encoded = (byte[][]) in.readObject();
Just read the int after u read map.The correct code would be :-
public void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
boxHeight = in.readInt();
boxWidth = in.readInt();
mapHeight = in.readInt();
mapWidth = in.readInt();
map = ImageIO.read(in);
in.readInt();// you read this int and assign it to the object as you wish
encoded = (byte[][]) in.readObject();
int tileSetSize = in.readInt();
for(int i = 0; i < tileSetSize; i++){
tileSet.add(ImageIO.read(in));
}
}

Display data on console and also save data to text file.

So here is my code, it seems to work, but it just prints out the info on file rather than doing both (displaying data on console and saving the information to a text file). Help appreciated.
// imports
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
public class DTM {
// The main method for our Digital Terrain Models
/** #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
//Prints the console output on a text file (Output.txt)
PrintStream out = new PrintStream(new FileOutputStream("output.txt"));
System.setOut(out);
//Declare some variables
int aRows = 401;
int bCols = 401;
String DMTfile = "sk28.asc";
//Declare some tables
double data[][] = new double[aRows][bCols];
BufferedReader file = new BufferedReader(new FileReader(DMTfile));
//Write data into array
for (int i = 0; i < aRows; i++) {
String rowArray[] = file.readLine().split(" ");
for (int j = 0; j < bCols; j++) {
data[i][j] = Double.parseDouble(rowArray[j]);
}
}
//Closing the file
file.close();
//print out the array
for (int i = 0; i < aRows; i++) {
for (int j = 0; j < bCols; j++) {
System.out.println(data[i][j]);
}
}
// this hold's the smallest number
double high = Double.MIN_VALUE;
// this hold's the biggest number
double low = Double.MAX_VALUE;
//initiate a "For" loop to act as a counter through an array
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++)
//determine the highest value
if (data[i][j] > high) {
high = data[i][j];
}
//determine the lowest value
else if (data[i][j] < low) {
low = data[i][j];
}
}
// Code here to find the highest number
System.out.println("Peak in this area = " + high);
// Code here to find the lowest number
System.out.println("Dip in this area = " + low);
}
}
Try the Apache Commons TeeOutputStream.
Untested, but should do the tric:
outStream = System.out;
// only the file output stream
OutputStream os = new FileOutputStream("output.txt", true);
// create a TeeOutputStream that duplicates data to outStream and os
os = new TeeOutputStream(outStream, os);
PrintStream printStream = new PrintStream(os);
System.setOut(printStream);
You're merely redirecting standard output to a file instead of the console. As far as I know there is no way to automagically clone an output onto two streams, but it's pretty easy to do it by hand:
public static void multiPrint(String s, FileOutputStream out){
System.out.print(s);
out.write(s);
}
Whenever you want to print you just have to call this function:
FileOutputStream out=new FileOutputStream("out.txt");
multiPrint("hello world\n", out);

Reading CSV file without third-party libraries

I'm trying to read a csv file into either an ArrayList or a String [][] array. In this I'm trying to read it into a list and then form the list, using a tokenizer, into an array. The csv file have 7 columns (A - G) and 961 rows (1-961). My for loop for the 2D array keeps returning a null pointer, but I think it should be working..
public class FoodFacts
{
private static BufferedReader textIn;
private static BufferedReader foodFacts;
static int numberOfLines = 0;
static String [][] foodArray;
public static String aFact;
static int NUM_COL = 7;
static int NUM_ROW = 961;
// Make a random number to pull a line
static Random r = new Random();
public static void main(String[] args)
{
try
{
textIn = new BufferedReader(new InputStreamReader(System.in));
foodFacts= new BufferedReader(new FileReader("foodfacts.csv"));
Scanner factFile = new Scanner(foodFacts);
List<String> facts = new ArrayList<String>();
String fact;
System.out.println("Please type in the food you wish to know about.");
String request = textIn.readLine();
while ( factFile.hasNextLine()){
fact = factFile.nextLine();
StringTokenizer st2 = new StringTokenizer(fact, ",");
//facts.add(fact);
numberOfLines++;
while (st2.hasMoreElements()){
for ( int j = 0; j < NUM_COL ; j++) {
for (int i = 0; i < NUM_ROW ; i++){
foodArray [j][i]= st2.nextToken(); //NULL POINTER HERE
System.out.println(foodArray[j][i]);
}
}
}
}
}
catch (IOException e)
{
System.out.println ("Error, problem reading text file!");
e.printStackTrace();
}
}
}
Initialize your foodArray as foodArray = new String[NUM_ROW][NUM_COL]; before using it.
Also, there is no need for inner for loop as you are reading one row at a time.
use numberOfLines as row:
while ( factFile.hasNextLine() && numberOfLines < NUM_ROW){
fact = input.nextLine();
StringTokenizer st2 = new StringTokenizer(fact, ",") ;
//facts.add(fact);
while (st2.hasMoreElements()){
for ( int j = 0; j < NUM_COL ; j++) {
foodArray [numberOfLines][j]= st2.nextToken();
System.out.println(foodArray[numberOfLines][i]);
}
}
numberOfLines++;
}
Alternatively, I think you can use split to get all columns as once e.g.
while ( factFile.hasNextLine() && numberOfLines < NUM_ROW){
fact = input.nextLine();
foodArray [numberOfLines++] = fact.split(",");
}
One question: Is there any specific purpose for declaring all variables as static class variables? Most of them fit as local variable inside the method e.g. numberOfLines?
You can use this String [][] foodArray = csvreadString(filename); method. It actually reads the file twice, but I don't know how to get the csv dimension without reading the data (you need the dimension in order to initialize the array), and this is very fast in comparison to other methods that I tried.
static public class PairInt {
int rows = 0;
int columns = 0;
}
static PairInt getCsvSize(String filename) throws Throwable {
PairInt csvSize = new PairInt();
BufferedReader reader = new BufferedReader(new FileReader(new File(filename)));
String line;
while ((line = reader.readLine()) != null) {
if (csvSize.columns == 0) {
csvSize.columns = line.split(",").length;
}
csvSize.rows++;
}
reader.close();
return csvSize;
}
static String[][] csvreadString(String filename) throws Throwable {
PairInt csvSize = getCsvSize(filename);
String[][] data = new String[csvSize.rows][csvSize.columns];
BufferedReader reader = new BufferedReader(new FileReader(new File(filename)));
for (int i = 0; i < csvSize.rows; i++) {
data[i] = reader.readLine().split(",");
}
return data;
}

Categories