valgrind
c言語で開発を行っているときにちょいちょいお世話になるフリーのツール
valgrindの使い方のまとめです。
valgrindはlinuxベースで動作する、メモリーリーク・メモリ不正アクセス・プロファイルなどのチェックができる開発支援のツールです。
WindowsだとVisualStudioとかでいろいろやってくれちゃうんですが、gdbとかじゃここまでやってくれないのでこのツールを使ってます。
とりあえずインストール
http://valgrind.org/downloads/current.html
からソースをダウンロードします。
以下のコマンドでインストール完了です。
良くあるパターンですね。
$ tar xvf valgrind-3.9.0.tar.bz2 $ cd valgrind-3.9.0 $ ./configure $ make $ su # make install
valgrindには以下のサブツールが含まれています。
- memcheck メモリチェックツール(メインのツール)
- cachegrind キャッシュプロファイラ
- exp-bbv 基本ブロックベクター生成ツール
- helgrind スレッドエラーの検出
- callgrind コールグラフ生成。
- exp-dhat 動的ヒープ解析
- lackey ツールのサンプルコード
- none 何もしないツール
- drd スレッドエラーの検出
- exp-sgcheck スタック配列とグローバル配列のオーバーラン検出
- massif ヒーププロファイラ
wikipedia参照しただけなので良くわからないツールが満載…
とりあえず次回はメインのmemcheckの使い方です。
viの文字コード指定
いつも忘れてしまう、viで文字コード指定して開く方法
自動判別とかしてくれないのだろうか…
開くときに指定する場合は
vi -c ":e ++enc=euc-jp" xxxx.txt
開いた後に指定する場合は、viのコマンドで
:e ++enc=euc-jp
でOK
指定できる文字コードは
iso-2022-jp cp932 sjis euc-jp utf-8
があるみたい。
てか自動判別もできるみたい
~/.vimrcに以下を追加するらしい
set encoding=utf-8 <--OSのデフォルト文字コード set fileencodings=iso-2022-jp,cp932,sjis,euc-jp,utf-8 <--左から順に当てていくらしい
CVSパーサー
業務でCSVの読み込みが必要だったのでクラス作成。
いつも適当に作っていたのですが、今回ある程度ちゃんと作ってみたので公開します。
動きとしては、
- セパレータはカンマ
- ダブルクオートで囲まれている中の改行は、1データの終わりではない
- ダブルクオートが続いていた場合、1つのダブルクオートの文字として扱う
こんな感じ
んでソース
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; /** * * CSV1行の情報保持クラス * * @author xxxxx * */ final class RowInfo{ /** * 読み込み元ファイルの行番号 */ int lineNum; /** * 1分のトークン */ String[] csv; /** * コンストラクタ * @param lineNum * @param csv */ public RowInfo(int lineNum,String[] csv){ this.lineNum = lineNum; this.csv = csv; } } /** * * CSV解析クラス * * @author xxxx * */ public class CSVParser { /** * * コンストラクタ * * @param colomSize */ public CSVParser(int colomSize) { this.colomSize = colomSize; } public CSVParser() { } /** * 1ファイル分のCSV情報 */ ArrayList<RowInfo> csvList = new ArrayList<RowInfo>(); /** * CSVのカラムサイズ */ public int colomSize = -1; public int getCSVSize(){ return csvList.size(); } public String[] getCSV(int index){ return csvList.get(index).csv; } public int getLineNum(int index){ return csvList.get(index).lineNum; } /** * 1ファイル分のCSV文字列設定 * @param str */ public void setSource(String[] str){ source = str; } /** * パース前のオリジナル文字列 */ private String[] source = null; /** * CSVファイルのパース<br> * パースのルールは<br> * ダブルクオートがあったら、それ以降のカンマ、改行はデータとして取り込む<br> * ダブルクート中の連続したダブルクオートは一つのダブルクオートとして取り込む<br> * 先頭行が#の場合コメントとして読み飛ばす<br> * */ public void parse(){ boolean inDoubleQuote = false; StringBuilder token = new StringBuilder(); ArrayList<String> rowCsv = new ArrayList<String>(); int lineNum = 0; boolean isEof = false; for(int i = 0;i < source.length;i++){ // ファイルの最終行か? if(source.length - 1 == i){ isEof = true; } String lineStr = source[i]; if(lineStr == null){ lineStr = ""; } // ダブルクオート中ではない場合(新規行の解析開始) if(!inDoubleQuote){ lineNum = i + 1; // 行番号を保持 // 空行の場合、スキップ if(lineStr.length() == 0){ continue; } // コメントの場合スキップ char comment = lineStr.charAt(0); if(comment == '#'){ continue; } } // 一行分のCSVをパース for(int j = 0;j < lineStr.length();j++){ char curChar = lineStr.charAt(j); char nextChar = '\0'; boolean isEndLine = false; // 一つ先の文字も取得する if(j + 1 < lineStr.length()){ nextChar = lineStr.charAt(j + 1); isEndLine = false; }else{ isEndLine = true; } // クオートじゃないときの処理 if(!inDoubleQuote){ // クオート処理開始 if(curChar == '"'){ inDoubleQuote = true; } // カンマの場合1トークン終了 else if(curChar == ','){ rowCsv.add(token.toString()); token = new StringBuilder(); } // 上記以外はトークンに追加 else{ token.append(curChar); } } // クオート中の処理 else{ // クオートが続いてたら一つだけトークンに追加(エスケープ) if(curChar == '"' && nextChar == '"'){ j += 1; token.append(curChar); } // クオートの場合クオート処理終了 else if(curChar == '"'){ inDoubleQuote = false; } // 上記以外はトークンに追加 else{ token.append(curChar); } } // 行の末尾の場合1トークン終了(しかし、クオート中の場合は次の行も継続) if(isEndLine && !inDoubleQuote){ rowCsv.add(token.toString()); token = new StringBuilder(); } } // クオート中でないか、最終行の場合 // 1行解析終了なので配列に取り込む if(!inDoubleQuote || isEof){ // カラム数が足りない場合、nullでカラム数を追加する if(colomSize > 0){ int addNum = colomSize - rowCsv.size(); for(int j = 0;j < addNum;j++){ rowCsv.add(null); } } RowInfo rowInfo = new RowInfo(lineNum, rowCsv.toArray(new String[rowCsv.size()])); csvList.add(rowInfo); rowCsv = new ArrayList<String>(); } // クオート内の場合、次の行もパースを継続 else{ token.append("\n"); } } } }
んで、使い方
void main(String[] args){ String filePath = "xxx.csv"; FileInputStream is = null; InputStreamReader in = null; BufferedReader br = null; try{ // CSVファイル読み込み File file = new File(filePath); is = new FileInputStream(file); in = new InputStreamReader(is); br = new BufferedReader(in); // 一行づつ読み出し配列に格納 String line; ArrayList<String> lines = new ArrayList<String>() ; while( (line=br.readLine())!=null ){ lines.add(line); } // CSV解析 CSVParser csvParser = new CSVParser (); csvParser.setSource(new String[lines.size()]); csvParser.parse(); String[] csv = csvParser.getCSV(0); }finally{ if(is != null){ is.close(); } if(in != null){ in.close(); } if(br != null){ br.close(); } } } }
リサイクルBin
Oracleで作業してる際に、ふとテーブル一覧を確認したらBIN$xxxxxとかいうテーブルが大量に・・・
なんだ?これと調べてみたらリサイクルBinというらしい。
テーブルをドロップしてもこのBINというテーブル名で残るらしい、
Windowsのごみ箱みたいなもの、んでそれを削除するSQL
Purge RecycleBin;
すっきり☆
ちなみにリサイクルBinを確認する方法
show recyc;
リサイクルBinを復元する方法
flashback table 復元対象のテーブル名 to before drop; flashback table BINxxxxx to before drop;
あとリサイクルBinを使用しないで削除する方法
drop table テーブル名 purge;
起動引数解析
JavaでCUIプログラムを作成する際に、毎度起動引数解析処理をコーディングしてたので一つの汎用クラスを作ってみました。
ライブラリを使っても良いんだけど、基本自前で作成します。(ライセンスとか面倒だし…)import java.util.ArrayList; import java.util.Iterator; /** * * 起動引数のオプション情報クラス * * @author xx * */ final class OptionInfo{ /** * オプション名 */ String optionName = null; /** * このオプションに値があるかの有無 */ boolean isValue = false; /** * ヘルプのコメント */ String comment = null; /** * このオプションの値 */ String value = null; /** * このオプションが起動引数に存在しているか */ boolean isExist = false; /** * * コンストラクタ * * @param optionName オプション名 * @param isValue オプションの後に値が設定されるかの有無 * @param comment ヘルプ表示時の説明文 */ public OptionInfo(String optionName,boolean isValue,String comment){ this.optionName = optionName; this.isValue = isValue; this.comment = comment; } } /** * * 起動引数解析クラス * * @author xxxx * */ public class ArgsParser { /** * オプション情報 */ ArrayList<OptionInfo> optionInfo = new ArrayList<OptionInfo>(); /** * オプション以外の引数格納配列 */ ArrayList<String> values = new ArrayList<String>(); /** * * オプション設定の追加 * * @param optionName オプション名 * @param isValue オプションの後に値が設定されるかの有無 * @param comment ヘルプ表示時の説明文 */ public void addOption(String optionName,boolean isValue,String comment){ optionInfo.add(new OptionInfo(optionName,isValue,comment)); } /** * * 指定オプションが起動引数に存在しているか * * @param optionName オプション名 * @return オプションがあった場合true */ public boolean isExist(String optionName){ for (Iterator<OptionInfo> i = optionInfo.iterator(); i.hasNext();) { OptionInfo o = i.next(); if(o.optionName.equals(optionName)){ return o.isExist; } } return false; } /** * * 指定オプションの値を取得 * * @param optionName オプション名 * @return オプションの値 */ public String getOptionValue(String optionName){ for (Iterator<OptionInfo> i = optionInfo.iterator(); i.hasNext();) { OptionInfo o = i.next(); if(o.optionName.equals(optionName)){ return o.value; } } return null; } /** * 起動引数の値を取得(先頭) * @return 起動引数の値 */ public String getValue(){ if(values.size() == 0){ return null; } return values.get(0); } /** * 指定位置の起動引数の値を取得 * @param idx * @return 起動引数の値 */ public String getValue(int idx){ if(values.size() <= idx){ return null; } return values.get(idx); } /** * 起動引数の数(オプション以外の) * @return */ public int getValueNum(){ return values.size(); } /** * 解析処理 * @param args */ public void parse(String[] args){ for (int i = 0; i < args.length; i++) { String arg = args[i]; boolean isOption = false; // オプションの取得処理(同一オプションがあった場合後方優先) for (int j = 0;j < optionInfo.size();j++){ OptionInfo o = optionInfo.get(j); if(arg.equals(o.optionName)){ o.isExist = true; if(o.isValue){ if(i < args.length){ i += 1; o.value = args[i]; }else{ // 値が存在していない場合はエラー throw new IllegalArgumentException(String.format("オプション[%s]に値がありません", o.optionName)); } } isOption = true; } } // オプションでなければ値を保持 if(!isOption){ values.add(arg); } } } /** * ヘルプ表示 * 引数は説明文、オプションは自動生成 */ public void printHelp(String message){ System.out.println(message); for (Iterator<OptionInfo> i = optionInfo.iterator(); i.hasNext();) { OptionInfo o = i.next(); System.out.println(String.format(" %s : %s", o.optionName,o.comment)); } } }
んで、使い方サンプル
void main(String[] args){ ArgsParser arqgsParser = new ArgsParser(); // オプション設定 arqgsParser.addOption("-c", true, "-cの説明"); arqgsParser.addOption("-d", true, "-dの説明"); try{ arqgsParser.parse(args); }catch(Exception e){ arqgsParser.printHelp("使い方 xxx "); return; } // オプション取得 String cStr = ""; if(arqgsParser.isExist("-c")){ cStr = arqgsParser.getOptionValue("-c"); } String dStr = ""; if(arqgsParser.isExist("-d")){ dStr = arqgsParser.getOptionValue("-d"); } // 起動引数取得 String value= arqgsParser.getValue(); }
いろいろ突っ込みどころはあると思いますが、ざっくりとこんな感じ
初投稿
プログラムメインの自分用備忘録としてつらつらと書いていきたいと思います。
自分以外でも参考にしてもらえるとうれしいです。