June 2008

File I/O Part 1

I love to learn and try new languages. Not only is learning a new language fun, many times it teaches me something new about a language that I am already familiar with. The only problem that I have with learning so many languages, is keeping them straight. I decided that I would take a few of the dynamic languages I use most often and compile a list of how to handle File I/O with each of them. If you have a Dynamic language(part 2 of this post will be on static languages) not represented below or have another method of File I/O with the represented languages, please add to the list with its respective File I/O code:D
Without further ado…

//Groovy open file for writing
def target ="filename"
File wf= new File(target)
wf.write( "I am in your file eating your space" )

//Groovy open file for appending
def target ="filename"
File af= new File(target)
af.append("I have all of your base")

//Groovy read each line in file
new File("filename").eachLine{line-> println line}

//Groovy read whole document and put into List

List lines = new File("filename").readLines()
//lines contains two lines that we need
println "first line  $lines[0]"
println "second line $lines[1]"

//Groovy reading one line
File rf= new File("filename") //open for reading
//read first line, trim, assign to tmp
rf.withReader { line ->tmp = line.readLine().trim()}

//Groovy test if file exists
File src = new File(srcFile)
if (src.exists() ){ println "I exist"}
else{println "I don't exist"}

#Ruby openfile for reading
fh = File.new(path, "r")  # open file "path" for reading only
fh.close

#Ruby open file for writing
fout   = File.new(path, "w")  # open file "path" for writing only
fout.puts "Up, Up, Down, Down, Left, Right, Left, Right, B, A, Select, Start"
fout.close

#Ruby open file for apending
fa= File.new("DeleteMe.txt","a")
fa.puts "I am at the end of file"
fa.close

#Ruby read eachline in a file
File.open("file").each { |line| p line}

#Ruby read entire file to string
fh = File.new(filename)
str = fh.read

#Ruby read entire file into array(each line is an element in the array)
fh = File.new(filename)
str = fh.readlines

#Python Write a file
fout = open("DeletMe.txt", "w")
fout.write("Writing to fout\nCheck it out!")
fout.close()

#Python Read an entire file
fin = open("ReadingTest.txt", "r")
fin_text =  fin.read()
fin.close()
print fin_text

#Python read entire file into list
fin = open("ReadingTest.txt", "r")
txt= fin.readlines()
fin.close()
print txt[0]

#Python append to a file
fh= open ( 'DeleteMe.txt', 'a' )
fh.write ( '\n\n\nBottom line.' )
fh.close()

#Perl reading a file
open(FILE,  '<', $file) or die "Can't read $file: $!\n";
while(<FILE>)
{
print ;
}

#Perl append to a file
open(FILE, '>>', $file) or    die "Can't append to $file: $!\n";
print FILE "text";
close(FILE);

#Perl read and write to a file
#+< allows reading and writing, and keeps the data that was
#already in the file.  open() will fail if file doesn't exist.
open(FILE, "+<$file" ) or die ("Can't  read|write: $file\n");
close(FILE);

#Perl read and write to a file
#+>allows writing and reading, but replaces/overwrites the
#data in the file if the file exists. Creates it if it doesn't exist.
open(FILE, "+>$file" ) or die ("Can't write or read:$file \n");

close(FILE);

PHP code doesn’t display properly within WordPress, so here is an image of the code

PHP File I/O

code
Linux
perl
php
python
Ruby

Comments (4)

Permalink

Handling Ruby’s String.each_char Iterator

Ahh the joys of iterators. I can’t say enough about how much they make my life easier. They are just so darn handy. Life was good in my Ruby world until I needed to iterate through the characters in a string. Thinking to myself, “there has got to be a method that does this,” I looked up Ruby’s String class and saw just what the doctor ordered… each_char.

Feeling pretty proud that my favorite language had this baked right in, I was only to happy to inject it into my code and test it out. That is until I recieved the dreaded NoMethodError: undefined method `each_char’ . Eeek, what did I do wrong? Did I mispell the method…..Nope, did I call it correctly…..Yep. Well, what the heck is going on?

After multiple attempts to find the answer on Google, I finally posted my problem to the ruby-talk group. I was told that the Ruby 1.8 String implementation that I was using only understood bytes and that I could use require ‘jcode’ to get the iterator to work the way I wanted. I did some looking around and I am not sure this is a great solution, after all, I could have easily used the each_byte{|f| f.chr} to iterate through and convert accordingly. I don’t understand why something that is documented as part of the class, does not work.

It would really help if there was an easy to search area on the net dedicated to language quirks for people trying to get a better grasp of their programming language of choice. Maybe that will be my next ROR project.

As it turns out, my Ruby 1.8.7 installation on my Fedora core 9 works as advertised.

code
Linux
Ruby

Comments (14)

Permalink

su vs. “su -” The Mystery Revealed

Inquiring minds want to know, what is this su - and why is it different than su? Well, if you are like me, you didn’t even know that su - existed. I ran into this problem when I was trying to add a new user to a new Linux machine. Remote root login was disabled(for obvious reasons:D) and I was logged in with my regular non-privileged user account. Well, normally the story goes like this…

  1. su
  2. Authenticate
  3. useradd account
  4. set password
  5. log out of privileged account
  6. Take coffee break from all the hard work and call it a day

No so today:( . When I attempted to run step three(useradd), I received a command not found error. “That’s weird” I thought. How could a machine not have this basic command. I looked in the bin directory to see if it was some kind of path error I was having. Thinking that this was the case, I was shocked to see that none of the user commands(adduser, usermod, deluser) where there.

After a few minutes of scratching my head, I asked someone more versed in Linux than I what they thought. After walking through each of the steps I had taken, my mistake was easily spotted. I hadn’t added the ‘-’ to the su command. Thinking that the explanation was weird, I checked with google for the su - command. Sure enough, the link to Wikipedia had this to say about it,

Optionally, you can use a hyphen with su to invoke a login shell and assume the target user’s complete user environment:

I am glad I had someone to point this out to me… It could have been a longer and very frustrating ordeal. It was also a lesson for me to refer more to the man pages(it had the answer there too). I hope this blog entry helps someone else who is confronted with this situation.

Administration
Linux

Comments (0)

Permalink

Adding Functionality to Ruby Strings

Ok, here is the scoop. I was working on a project using Ruby and needed to grab three characters from a string skipping one character in between.

ex –>  “123456789″    would become 234 and 567

I thought this would be a great opportunity to try out blocks in Ruby and test open classes

class String
   def blocker(sizeOfGroup,offset)
     while(val=self.slice!(0..offset.abs-1))
        break if val.to_s.length < 1
        yield  self.slice!(0..(sizeOfGroup.abs-1))
      end
  end
end


here is the code I used to test with


string = "12345678910"
ary=[]
string.blocker(3,-1){|v| ary.push(v)}
ary.each{|i|puts i}
puts "her is ary "+ary.inspect

And this is the result.

>>> test.rb

234
678
10
her is ary ["234", "678", "10"]

This was definitely a fun experiment and I can't wait to try out more stuff. If you haven't played around with blocks, give it a try...you just might like it.

code

Comments (0)

Permalink

MD5 goodness in Java

A while back I wrote a program which would compare multiple files based on their MD5 checksums. The program can run in Command-Line mode(more powerful, supports batch processing)

Picture of MD5 integrity checker Command line mode
and GUI mode.
Picture of MD5 integrity checker GUI

Running via command line with the ‘?’ flag will allow the user to view all the flags that can be used by the program. The purpose was to make sure a file hadn’t been changed without my knowledge, by keeping the old checksum and comparing it to the newly generated one.

I ran into a few hurdles along the way and thought that I would share what I encountered to give back to the developer community that has helped me a great deal. If your a Jedi Master of Java, then this probably is something you may not want to waste your time on. Otherwise, I hope this is useful.

Now on with the program. By the way, suggestions for better coding practices are appreciated :D

The first snafu I encountered was how to actually create and use a message digest. There are quite a few resources out there, and by all means check em out. After all my research, this is what I came up with for the MD5 class

package md5IntegrityCheck;

import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5 {
private byte[] raw;

private String HashValue = "";

private FileIO outputToFile = new FileIO();

private MessageDigest md;

public MD5(String FileToHash) throws UnsupportedEncodingException,
NoSuchAlgorithmException {
try {
// Obtain a message digest object.
md = MessageDigest.getInstance("MD5");
// Calculate the digest for the given file.
FileInputStream in = new FileInputStream(FileToHash);
byte[] buffer = new byte[8192];
int length;
while ((length = in.read(buffer)) != -1) {
md.update(buffer, 0, length);
}
raw = md.digest();
createHashValue();
in.close();
}

catch (Exception ex) {
/**
* print to -e error path or print file in local directory called
* IntegrityCheckError.txt
*/
outputToFile.printToFile("no_E_IntegrityCheckError.txt", ex
.getMessage());
killProgram();
}

}

public MD5(String FileToHash, String ErrorPath)
throws UnsupportedEncodingException, NoSuchAlgorithmException {
try {
// Obtain a message digest object.
md = MessageDigest.getInstance("MD5");

// Calculate the digest for the given file.
FileInputStream in = new FileInputStream(FileToHash);
byte[] buffer = new byte[8192];
int length;
while ((length = in.read(buffer)) != -1) {
md.update(buffer, 0, length);
}
raw = md.digest();
createHashValue();
in.close();
} catch (Exception ex) {// failed due to write or something
/**
* print to -e error path or print file in local directory called
* IntegrityCheckError.txt
*/
if (ErrorPath.length() > 0) {
// write to file
outputToFile.printToFile(ErrorPath, ex.getMessage());
}
killProgram();
}
}

/**
*
* @param word
*            Function sets the value of the HashValue
* @return void
*/

public String setHashValue(String word) {
HashValue = word;
return HashValue;
}
/**
*
* @return the Hashed value for the file
*/
public String getHashValue() {
return HashValue;
}

public void createHashValue() {
// for (byte b : raw) { // java 5.0 syntax replace below for older 1.4
String strBuildup="";
for (int k = 0; k < raw.length; k++) {
byte b = raw[k];
String temp = Integer.toHexString(b & 0xFF);
/*
* toHexString has the side effect of making stuff like 0x0F only
* one char F(when it should be '0F') so I check the length of string
*/
if (temp.length() < 2) {
// System.out.println("here is offending value" +temp);
temp = "0" + temp;
}
temp = temp.toUpperCase();
//this.setHashValue((HashValue + temp));
strBuildup+=temp;
}
this.setHashValue((strBuildup ));

//return HashValue;

}
/**
*
* @return the digest for the current MD5 object
*/
public byte[] getDigest() {
  return raw;
}

/**
*
* @param HashToCompare
*            -the hash number(Message Digest) to compare against
* @return flag
*/
public boolean isEqual(byte[] HashToCompare) {
boolean flag = false;
  if (MessageDigest.isEqual(raw, HashToCompare)) {
    flag = true;
  }
  return flag;
}

/**
*
* @param Compares
*            two Hash values represented in Hex byte[] format
* @return flag
*/
public boolean isEqual(byte[] InHash, byte[] HashToCompare) {
 boolean flag = false;
   if(MessageDigest.isEqual(InHash, HashToCompare)) {
      flag = true;
   }
   return flag;
 }
/**
* Kill the program
*/
 private void killProgram() {
    System.exit(3);
  }
}


The thing that tripped me up the most was the createHashValue() method. The comments explain the problem I had using Integer.toHexString.

The second problem I had was creating a drag and drop gui. To this day, I haven’t fully grasped DnD, so I used a lot of on-line resources to get it to work. It is only right that I give the code back to the world. I ended up using Java 1.6 to get the gui to work. The following is the code for handling the dropped file
package md5IntegrityCheck;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.TransferHandler;

/**
* this is going to have to have an md5 object and run the code here
*
* @author javazquez
*
*/
class FileDropHandler extends TransferHandler {
/**
*
*/
private static final long serialVersionUID = 1L;

/**
*
*/

MD5 firstHash = null;

private JTextArea output;

private JLabel errorMsg;

private String fileText = "";

private boolean test = false;

private boolean same = true;

public boolean canImport(TransferSupport supp) {
/* for the demo, we'll only support drops (not clipboard paste) */
if (!supp.isDrop()) {
return false;
}

/* return false if the drop doesn't contain a list of files */
if (!supp.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return false;
}

/*
* check to see if the source actions (a bitwise-OR of supported
* actions) contains the COPY action
*/
boolean copySupported = (COPY & supp.getSourceDropActions()) == COPY;

/* if COPY is supported, choose COPY and accept the transfer */
if (copySupported) {
supp.setDropAction(COPY);
return true;
}

/*
* COPY isn't supported, so reject the transfer.
*
* Note: If you want to accept the transfer with the default action
* anyway, you could instead return true.
*/
return false;
}

public boolean importData(TransferSupport supp) {
if (!canImport(supp)) {
return false;
}

/* fetch the Transferable */
Transferable t = supp.getTransferable();

try {

/* fetch the data from the Transferable */
Object data = t.getTransferData(DataFlavor.javaFileListFlavor);

/* data of type javaFileListFlavor is a list of files */
List fileList = (List) data;

/*
* loop through the files in the file list and compare the first MD5
* with the rest
*/

for (int j = 0; j < fileList.size(); j++) {

File file = (File) fileList.get(j);

MD5 fileHashtoCompare = new MD5(file.getAbsolutePath());
if (!test) {
firstHash = fileHashtoCompare;
}
output.append(fileHashtoCompare.getHashValue() + "\t"
+ file.getName() + "\n");

if (test) {
if (fileHashtoCompare.isEqual(firstHash.getDigest(),
fileHashtoCompare.getDigest())
&& same) {
fileText = "             \t\tThese files are the same";
} else {
fileText = "             \t\tThese files are the DIFFERENT";
same = false;
}
errorMsg.setText(fileText);
}
test = true;

// System.out.println(file.getName() + fileText);

/*
* This is where you place your code for opening the document
* represented by the "file" variable. For example: - create a
* new internal frame with a text area to represent the document -
* use a BufferedReader to read lines of the document and append
* to the text area - add the internal frame to the desktop
* pane, set its bounds and make it visible
*/
}
} catch (UnsupportedFlavorException e) {
return false;
} catch (IOException e) {
return false;
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return true;
}

public void setOutput(JTextArea jta) {
output = jta;
}

public void setOutput(JLabel jta) {
errorMsg = jta;
}

public String getText() {
return fileText;
}

public void clearAll() {
fileText = "";
test = false;
same = true;

}
}

A link to the program is here. Use it however you please.

code

Comments (1)

Permalink