KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > Ostermiller > util > LineEnds


1 /*
2  * Adjusts line endings.
3  * Copyright (C) 2001 Stephen Ostermiller
4  * http://ostermiller.org/contact.pl?regarding=Java+Utilities
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * See COPYING.TXT for details.
17  */

18
19 package com.Ostermiller.util;
20
21 import java.io.*;
22 import gnu.getopt.*;
23 import java.text.MessageFormat JavaDoc;
24 import java.util.ResourceBundle JavaDoc;
25 import java.util.Locale JavaDoc;
26
27 /**
28  * Stream editor to alter the line separators on text to match
29  * that of a given platform.
30  * More information about this class is available from <a target="_top" HREF=
31  * "http://ostermiller.org/utils/LineEnds.html">ostermiller.org</a>.
32  *
33  * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
34  * @since ostermillerutils 1.00.00
35  */

36 public class LineEnds {
37
38     /**
39      * Version number of this program
40      *
41      * @since ostermillerutils 1.00.00
42      */

43     public static final String JavaDoc version = "1.2";
44
45     /**
46      * Locale specific strings displayed to the user.
47      *
48      * @since ostermillerutils 1.00.00
49      */

50     protected static ResourceBundle JavaDoc labels = ResourceBundle.getBundle("com.Ostermiller.util.LineEnds", Locale.getDefault());
51
52     /**
53      * Converts the line ending on files, or standard input.
54      * Run with --help argument for more information.
55      *
56      * @param args Command line arguments.
57      *
58      * @since ostermillerutils 1.00.00
59      */

60     public static void main(String JavaDoc[] args){
61         // create the command line options that we are looking for
62
LongOpt[] longopts = {
63             new LongOpt(labels.getString("help.option"), LongOpt.NO_ARGUMENT, null, 1),
64             new LongOpt(labels.getString("version.option"), LongOpt.NO_ARGUMENT, null, 2),
65             new LongOpt(labels.getString("about.option"), LongOpt.NO_ARGUMENT, null, 3),
66             new LongOpt(labels.getString("windows.option"), LongOpt.NO_ARGUMENT, null, 'd'),
67             new LongOpt(labels.getString("dos.option"), LongOpt.NO_ARGUMENT, null, 'd'),
68             new LongOpt(labels.getString("unix.option"), LongOpt.NO_ARGUMENT, null, 'n'),
69             new LongOpt(labels.getString("java.option"), LongOpt.NO_ARGUMENT, null, 'n'),
70             new LongOpt(labels.getString("mac.option"), LongOpt.NO_ARGUMENT, null, 'r'),
71             new LongOpt(labels.getString("system.option"), LongOpt.NO_ARGUMENT, null, 's'),
72             new LongOpt(labels.getString("force.option"), LongOpt.NO_ARGUMENT, null, 'f'),
73             new LongOpt(labels.getString("quiet.option"), LongOpt.NO_ARGUMENT, null, 'q'),
74             new LongOpt(labels.getString("reallyquiet.option"), LongOpt.NO_ARGUMENT, null, 'Q'),
75             new LongOpt(labels.getString("verbose.option"), LongOpt.NO_ARGUMENT, null, 'v'),
76             new LongOpt(labels.getString("reallyverbose.option"), LongOpt.NO_ARGUMENT, null, 'V'),
77             new LongOpt(labels.getString("noforce.option"), LongOpt.NO_ARGUMENT, null, 4),
78         };
79         String JavaDoc oneLetterOptions = "dnrsfVvqQ";
80         Getopt opts = new Getopt(labels.getString("lineends"), args, oneLetterOptions, longopts);
81         int style = STYLE_SYSTEM;
82         boolean force = false;
83         boolean printMessages = false;
84         boolean printExtraMessages = false;
85         boolean printErrors = true;
86         int c;
87         while ((c = opts.getopt()) != -1){
88             switch(c){
89                     case 1:{
90                     // print out the help message
91
String JavaDoc[] helpFlags = new String JavaDoc[]{
92                         "--" + labels.getString("help.option"),
93                         "--" + labels.getString("version.option"),
94                         "--" + labels.getString("about.option"),
95                         "-d --" + labels.getString("windows.option") + " --" + labels.getString("dos.option"),
96                         "-n --" + labels.getString("unix.option") + " --" + labels.getString("java.option"),
97                         "-r --" + labels.getString("mac.option"),
98                         "-s --" + labels.getString("system.option"),
99                         "-f --" + labels.getString("force.option"),
100                         "--" + labels.getString("noforce.option"),
101                         "-V --" + labels.getString("reallyverbose.option"),
102                         "-v --" + labels.getString("verbose.option"),
103                         "-q --" + labels.getString("quiet.option"),
104                         "-Q --" + labels.getString("reallyquiet.option"),
105                     };
106                     int maxLength = 0;
107                     for (int i=0; i<helpFlags.length; i++){
108                         maxLength = Math.max(maxLength, helpFlags[i].length());
109                     }
110                     maxLength += 2;
111                     System.out.println(
112                         labels.getString("lineends") + " [-" + oneLetterOptions + "] <" + labels.getString("files") + ">\n" +
113                         labels.getString("purpose.message") + "\n" +
114                         " " + labels.getString("stdin.message") + "\n" +
115                         " " + StringHelper.postpad(helpFlags[0] ,maxLength, ' ') + labels.getString("help.message") + "\n" +
116                         " " + StringHelper.postpad(helpFlags[1] ,maxLength, ' ') + labels.getString("version.message") + "\n" +
117                         " " + StringHelper.postpad(helpFlags[2] ,maxLength, ' ') + labels.getString("about.message") + "\n" +
118                         " " + StringHelper.postpad(helpFlags[3] ,maxLength, ' ') + labels.getString("d.message") + "\n" +
119                         " " + StringHelper.postpad(helpFlags[4] ,maxLength, ' ') + labels.getString("n.message") + "\n" +
120                         " " + StringHelper.postpad(helpFlags[5] ,maxLength, ' ') + labels.getString("r.message") + "\n" +
121                         " " + StringHelper.postpad(helpFlags[6] ,maxLength, ' ') + labels.getString("s.message") + " (" + labels.getString("default") + ")\n" +
122                         " " + StringHelper.postpad(helpFlags[7] ,maxLength, ' ') + labels.getString("f.message") + "\n" +
123                         " " + StringHelper.postpad(helpFlags[8] ,maxLength, ' ') + labels.getString("noforce.message") + " (" + labels.getString("default") + ")\n" +
124                         " " + StringHelper.postpad(helpFlags[9] ,maxLength, ' ') + labels.getString("V.message") + "\n" +
125                         " " + StringHelper.postpad(helpFlags[10] ,maxLength, ' ') + labels.getString("v.message") + "\n" +
126                         " " + StringHelper.postpad(helpFlags[11] ,maxLength, ' ') + labels.getString("q.message") + " (" + labels.getString("default") + ")\n" +
127                         " " + StringHelper.postpad(helpFlags[12] ,maxLength, ' ') + labels.getString("Q.message") + "\n"
128                     );
129                     System.exit(0);
130                 } break;
131                 case 2:{
132                     // print out the version message
133
System.out.println(MessageFormat.format(labels.getString("version"), (Object JavaDoc[])new String JavaDoc[] {version}));
134                     System.exit(0);
135                 } break;
136                 case 3:{
137                     System.out.println(
138                         labels.getString("lineends") + " -- " + labels.getString("purpose.message") + "\n" +
139                         MessageFormat.format(labels.getString("copyright"), (Object JavaDoc[])new String JavaDoc[] {"2001", "Stephen Ostermiller (http://ostermiller.org/contact.pl?regarding=Java+Utilities)"}) + "\n\n" +
140                         labels.getString("license")
141                     );
142                     System.exit(0);
143                 } break;
144                 case 'd':{
145                     style = STYLE_RN;
146                 } break;
147                 case 'n':{
148                     style = STYLE_N;
149                 } break;
150                 case 'r':{
151                     style = STYLE_R;
152                 } break;
153                 case 's':{
154                     style = STYLE_SYSTEM;
155                 } break;
156                 case 'f':{
157                     force = true;
158                 } break;
159                 case 4:{
160                     force = false;
161                 } break;
162                 case 'V':{
163                     printExtraMessages = true;
164                     printMessages = true;
165                     printErrors = true;
166                 } break;
167                 case 'v':{
168                     printExtraMessages = false;
169                     printMessages = true;
170                     printErrors = true;
171                 } break;
172                 case 'q':{
173                     printExtraMessages = false;
174                     printMessages = false;
175                     printErrors = true;
176                 } break;
177                 case 'Q':{
178                     printExtraMessages = false;
179                     printMessages = false;
180                     printErrors = false;
181                 } break;
182                 default:{
183                     System.exit(1);
184                 }
185             }
186         }
187
188         int exitCond = 0;
189         boolean done = false;
190         for (int i=opts.getOptind(); i<args.length; i++){
191             boolean modified = false;
192             done = true;
193             File source = new File(args[i]);
194             if (!source.exists()){
195                 if(printErrors){
196                     System.err.println(MessageFormat.format(labels.getString("doesnotexist"), (Object JavaDoc[])new String JavaDoc[] {args[i]}));
197                 }
198                 exitCond = 1;
199             } else if (!source.canRead()){
200                 if(printErrors){
201                     System.err.println(MessageFormat.format(labels.getString("cantread"), (Object JavaDoc[])new String JavaDoc[] {args[i]}));
202                 }
203                 exitCond = 1;
204             } else if (!source.canWrite()){
205                 if(printErrors){
206                     System.err.println(MessageFormat.format(labels.getString("cantwrite"), (Object JavaDoc[])new String JavaDoc[] {args[i]}));
207                 }
208                 exitCond = 1;
209             } else {
210                 try {
211                     if(convert (source, style, !force)){
212                         if (printMessages){
213                             System.out.println(MessageFormat.format(labels.getString("modified"), (Object JavaDoc[])new String JavaDoc[] {args[i]}));
214                         }
215                     } else {
216                         if (printExtraMessages){
217                             System.out.println(MessageFormat.format(labels.getString("alreadycorrect"), (Object JavaDoc[])new String JavaDoc[] {args[i]}));
218                         }
219                     }
220                 } catch (IOException x){
221                     if(printErrors){
222                         System.err.println(args[i] + ": " + x.getMessage());
223                     }
224                     exitCond = 1;
225                 }
226             }
227         }
228         if (!done){
229             try {
230                 convert (System.in, System.out, style, !force);
231             } catch (IOException x){
232                 System.err.println(x.getMessage());
233                 exitCond = 1;
234             }
235         }
236         System.exit(exitCond);
237     }
238
239     /**
240      * The system line ending as determined
241      * by System.getProperty("line.separator")
242      *
243      * @since ostermillerutils 1.00.00
244      */

245     public final static int STYLE_SYSTEM = 0;
246     /**
247      * The Windows and DOS line ending ("\r\n")
248      *
249      * @since ostermillerutils 1.00.00
250      */

251     public final static int STYLE_WINDOWS = 1;
252     /**
253      * The Windows and DOS line ending ("\r\n")
254      *
255      * @since ostermillerutils 1.00.00
256      */

257     public final static int STYLE_DOS = 1;
258     /**
259      * The Windows and DOS line ending ("\r\n")
260      *
261      * @since ostermillerutils 1.00.00
262      */

263     public final static int STYLE_RN = 1;
264     /**
265      * The UNIX and Java line ending ("\n")
266      *
267      * @since ostermillerutils 1.00.00
268      */

269     public final static int STYLE_UNIX = 2;
270     /**
271      * The UNIX and Java line ending ("\n")
272      *
273      * @since ostermillerutils 1.00.00
274      */

275     public final static int STYLE_N = 2;
276     /**
277      * The UNIX and Java line ending ("\n")
278      *
279      * @since ostermillerutils 1.00.00
280      */

281     public final static int STYLE_JAVA = 2;
282     /**
283      * The Macintosh line ending ("\r")
284      *
285      * @since ostermillerutils 1.00.00
286      */

287     public final static int STYLE_MAC = 3;
288     /**
289      * The Macintosh line ending ("\r")
290      *
291      * @since ostermillerutils 1.00.00
292      */

293     public final static int STYLE_R = 3;
294
295     /**
296      * Buffer size when reading from input stream.
297      *
298      * @since ostermillerutils 1.00.00
299      */

300     private final static int BUFFER_SIZE = 1024;
301     private final static int STATE_INIT = 0;
302     private final static int STATE_R = 1;
303
304     private final static int MASK_N = 0x01;
305     private final static int MASK_R = 0x02;
306     private final static int MASK_RN = 0x04;
307
308     /**
309      * Change the line endings of the text on the input stream and write
310      * it to the output stream.
311      *
312      * The current system's line separator is used.
313      *
314      * @param in stream that contains the text which needs line number conversion.
315      * @param out stream where converted text is written.
316      * @return true if the output was modified from the input, false if it is exactly the same
317      * @throws BinaryDataException if non-text data is encountered.
318      * @throws IOException if an input or output error occurs.
319      *
320      * @since ostermillerutils 1.00.00
321      */

322     public static boolean convert(InputStream in, OutputStream out) throws IOException {
323         return convert(in, out, STYLE_SYSTEM, true);
324     }
325
326     /**
327      * Change the line endings of the text on the input stream and write
328      * it to the output stream.
329      *
330      * @param in stream that contains the text which needs line number conversion.
331      * @param out stream where converted text is written.
332      * @param style line separator style.
333      * @return true if the output was modified from the input, false if it is exactly the same
334      * @throws BinaryDataException if non-text data is encountered.
335      * @throws IOException if an input or output error occurs.
336      * @throws IllegalArgumentException if an unknown style is requested.
337      *
338      * @since ostermillerutils 1.00.00
339      */

340     public static boolean convert(InputStream in, OutputStream out, int style) throws IOException {
341         return convert(in, out, style, true);
342     }
343
344     /**
345      * Change the line endings of the text on the input stream and write
346      * it to the output stream.
347      *
348      * The current system's line separator is used.
349      *
350      * @param in stream that contains the text which needs line number conversion.
351      * @param out stream where converted text is written.
352      * @param binaryException throw an exception and abort the operation if binary data is encountered and binaryExcepion is false.
353      * @return true if the output was modified from the input, false if it is exactly the same
354      * @throws BinaryDataException if non-text data is encountered.
355      * @throws IOException if an input or output error occurs.
356      *
357      * @since ostermillerutils 1.00.00
358      */

359     public static boolean convert(InputStream in, OutputStream out, boolean binaryException) throws IOException {
360         return convert(in, out, STYLE_SYSTEM, binaryException);
361     }
362
363     /**
364      * Change the line endings of the text on the input stream and write
365      * it to the output stream.
366      *
367      * @param in stream that contains the text which needs line number conversion.
368      * @param out stream where converted text is written.
369      * @param style line separator style.
370      * @param binaryException throw an exception and abort the operation if binary data is encountered and binaryExcepion is false.
371      * @return true if the output was modified from the input, false if it is exactly the same
372      * @throws BinaryDataException if non-text data is encountered.
373      * @throws IOException if an input or output error occurs.
374      * @throws IllegalArgumentException if an unknown style is requested.
375      *
376      * @since ostermillerutils 1.00.00
377      */

378     public static boolean convert(InputStream in, OutputStream out, int style, boolean binaryException) throws IOException {
379         byte[] lineEnding;
380         switch (style) {
381             case STYLE_SYSTEM: {
382                  lineEnding = System.getProperty("line.separator").getBytes();
383             } break;
384             case STYLE_RN: {
385                  lineEnding = new byte[]{(byte)'\r',(byte)'\n'};
386             } break;
387             case STYLE_R: {
388                  lineEnding = new byte[]{(byte)'\r'};
389             } break;
390             case STYLE_N: {
391                  lineEnding = new byte[]{(byte)'\n'};
392             } break;
393             default: {
394                 throw new IllegalArgumentException JavaDoc("Unknown line break style: " + style);
395             }
396         }
397         byte[] buffer = new byte[BUFFER_SIZE];
398         int read;
399         int state = STATE_INIT;
400         int seen = 0x00;
401         while((read = in.read(buffer)) != -1){
402             for (int i=0; i<read; i++){
403                 byte b = buffer[i];
404                 if (state==STATE_R){
405                     if(b!='\n'){
406                         out.write(lineEnding);
407                         seen |= MASK_R;
408                     }
409                 }
410                 if (b=='\r'){
411                     state = STATE_R;
412                 } else {
413                     if (b=='\n'){
414                         if (state==STATE_R){
415                             seen |= MASK_RN;
416                         } else {
417                             seen |= MASK_N;
418                         }
419                         out.write(lineEnding);
420                     } else if(binaryException && b!='\t' && b!='\f' && (b & 0xff)<32){
421                         throw new BinaryDataException(labels.getString("binaryexcepion"));
422                     } else {
423                         out.write(b);
424                     }
425                     state = STATE_INIT;
426                 }
427             }
428         }
429         if (state==STATE_R){
430             out.write(lineEnding);
431             seen |= MASK_R;
432         }
433         if (lineEnding.length==2 && lineEnding[0]=='\r' && lineEnding[1]=='\n'){
434             return ((seen & ~MASK_RN)!=0);
435         } else if (lineEnding.length==1 && lineEnding[0]=='\r'){
436             return ((seen & ~MASK_R)!=0);
437         } else if (lineEnding.length==1 && lineEnding[0]=='\n'){
438             return ((seen & ~MASK_N)!=0);
439         } else {
440             return true;
441         }
442     }
443
444     /**
445      * Change the line endings on given file.
446      *
447      * The current system's line separator is used.
448      *
449      * @param f File to be converted.
450      * @return true if the file was modified, false if it was already in the correct format
451      * @throws BinaryDataException if non-text data is encountered.
452      * @throws IOException if an input or output error occurs.
453      *
454      * @since ostermillerutils 1.00.00
455      */

456     public static boolean convert(File f) throws IOException {
457         return convert(f, STYLE_SYSTEM, true);
458     }
459
460     /**
461      * Change the line endings on given file.
462      *
463      * @param f File to be converted.
464      * @param style line separator style.
465      * @return true if the file was modified, false if it was already in the correct format
466      * @throws BinaryDataException if non-text data is encountered.
467      * @throws IOException if an input or output error occurs.
468      * @throws IllegalArgumentException if an unknown style is requested.
469      *
470      * @since ostermillerutils 1.00.00
471      */

472     public static boolean convert(File f, int style) throws IOException {
473         return convert(f, style, true);
474     }
475
476     /**
477      * Change the line endings on given file.
478      *
479      * The current system's line separator is used.
480      *
481      * @param f File to be converted.
482      * @param binaryException throw an exception and abort the operation if binary data is encountered and binaryExcepion is false.
483      * @return true if the file was modified, false if it was already in the correct format
484      * @throws BinaryDataException if non-text data is encountered.
485      * @throws IOException if an input or output error occurs.
486      *
487      * @since ostermillerutils 1.00.00
488      */

489     public static boolean convert(File f, boolean binaryException) throws IOException {
490         return convert(f, STYLE_SYSTEM, binaryException);
491     }
492
493     /**
494      * Change the line endings on given file.
495      *
496      * @param f File to be converted.
497      * @param style line separator style.
498      * @param binaryException throw an exception and abort the operation if binary data is encountered and binaryExcepion is false.
499      * @return true if the file was modified, false if it was already in the correct format
500      * @throws BinaryDataException if non-text data is encountered.
501      * @throws IOException if an input or output error occurs.
502      * @throws IllegalArgumentException if an unknown style is requested.
503      *
504      * @since ostermillerutils 1.00.00
505      */

506     public static boolean convert(File f, int style, boolean binaryException) throws IOException {
507         File temp = null;
508         InputStream in = null;
509         OutputStream out = null;
510         boolean modified = false;
511         try {
512             in = new FileInputStream(f);
513             temp = File.createTempFile("LineEnds", null, null);
514             out = new FileOutputStream(temp);
515             modified = convert (in, out, style, binaryException);
516             in.close();
517             in = null;
518             out.flush();
519             out.close();
520             out = null;
521             if (modified){
522                 FileHelper.move(temp, f, true);
523             } else {
524                 if (!temp.delete()){
525                     throw new IOException(
526                         MessageFormat.format(
527                             labels.getString("tempdeleteerror"),
528                             (Object JavaDoc[])new String JavaDoc[] {temp.toString()}
529                         )
530                     );
531                 }
532             }
533         } finally {
534             if (in != null){
535                 in.close();
536                 in = null;
537             }
538             if (out != null){
539                 out.flush();
540                 out.close();
541                 out = null;
542             }
543         }
544         return modified;
545     }
546 }
547
Popular Tags