SQLの窓

2015年09月18日


CKEditor CDN を使用して、簡単に HTML コンテンツ作成エディタを利用できます

CKEditor CDN( full )
※ 最大化ボタンをクリックして利用できます


CKEditor はダウンロード可能なソフトウェアですが、設置せずとも CKEditor CDN でホスティングされているライブラリを使用してすぐに使えるようになります。

CKEditor CDN( full ) では、WEBアプリの画面を作成するのを補助する事を想定しています( 特に、TABLE 要素のメンテナンスに優れています / 他も対話式やドラッグドロップ可能なコンテンツもあります )

また、この目的に特化する為、いくつかの拡張用のコードを追加しています。

1) 全ての HTML 要素を書ける
2) p 要素を自動挿入しない
3) localStorage に保存するボタンを追加
(保存するボタン用コマンド登録時に、modes プロパティでソース表示時にも実行可能にする)
<script src="//cdn.ckeditor.com/4.5.3/full/ckeditor.js"></script>
<textarea name="editor1"></textarea>
<style type="text/css">
.cke_button__mybutton_icon {
	display: none !important;
}
.cke_button__mybutton_label {
	display : inline !important;
}
</style>
<script>
editor = CKEDITOR.replace( 'editor1', {
	allowedContent : true,
	enterMode : CKEDITOR.ENTER_BR,
	enableTabKeyTools : true
} );
editor.on( 'pluginsLoaded', function(){
	editor.addCommand( 'svData', {
		modes : { source : 1,wysiwyg : 1 },
		exec : function( editor )   {
			localStorage["_save_ck_code"] = editor.getData();
		}
	}); 
	editor.ui.addToolbarGroup( "user" );
	editor.ui.addButton( 'mybutton',   {
		label : '入力内容を保存', command : 'svData', toolbar: 'user'
	} );
	var editor_code = localStorage["_save_ck_code"];
	if(typeof editor_code == 'string'){
		editor.setData(localStorage["_save_ck_code"]);
	}
});
</script>

ボタンのテキストを表示させる為に、強制的に CSS を変更していますが、ボタンのラベルがデフォルトで非表示となっている為です。( アイコンを利用したい場合は、background で指定し直します )
.cke_button_label {
    display: none;
    padding-left: 3px;
    margin-top: 1px;
    line-height: 17px;
    vertical-align: middle;
    float: left;
    cursor: default;
    color: #474747;
    text-shadow: 0 1px 0 rgba(255,255,255,.5)
}
参考ページ

CKEDITOR.config
CKEDITOR.ui
CKEDITOR.editor

ボタンの追加だけでは、テキストがボタンに表示されなかったので、CSS で対応しています。




posted by lightbox at 2015-09-18 18:20 | Comment(0) | WEBサービス | このブログの読者になる | 更新情報をチェックする

2015年09月17日


Google Chrome 45.0.2454.93m コンボボックスのバグ( リストボックスでは起こりません )

いずれ改善されるのでしょうが、非常に発見しづらいバグではあります。optgroup に背景色を設定すると、その中の option の背景も同じ色になるので、option に #ffffff を設定しようとすると、反映されないというバグです。しかも、このバグは、size 属性を指定した『リストボックス』では起こらないです。


▼ 以下は画像ですが、左側がバグが発生している状態です
このバグの対症療法は、#ffffff の代りに #fffffe を使います

<style>
.mttl1 {
	background-color: #e0e0e0;
}
.mttl1 option {
	background-color: #fffffe;
}

.mttl2 {
	background-color: #ffe4c4;
}
.mttl2 option {
	background-color: #ffffff;
}
</style>
<select>
<option value="jiyunotsubasa" selected>自由の翼フォント</option>

<optgroup label="よく飛ばない鳥" class="mttl1">
<option value="cp_font" >チェックポイントフォント</option>
<option value="jiyucho" >じゆうちょうフォント</option>
</optgroup>

<optgroup label="ふぉんときゅーとがーる" class="mttl2">
<option value="jkg-l_2" >JKゴシック</option>
<option value="jkgm3" >JKゴシック M</option>
</optgroup>
</select>



posted by lightbox at 2015-09-17 21:12 | Comment(0) | Google Chrome | このブログの読者になる | 更新情報をチェックする

2015年09月13日


ViewSwitcher : 複数の画面または階層となる画面は、別 XML で定義して addView すると、Android Studio の Design で全ての画面をプレビューできます

activity_main.xml


image_1.xml


ViewSwitcher は、二つの View を切り替える事のできる ViewGroup ですが、ViewSwitcher の中で表示する二つの View をひとつづつ XML で定義して ViewSwitcher の addView で実際の画面を追加します。

主な特記事項

フリックによる画面切り替えを行う為、Detecting Common Gestures で解説されている GestureDetector を使用しています。また、イベントは GestureDetector.SimpleOnGestureListener を使用してイベントの記述を簡潔にしています。

onFling で、event2.getX() - event1.getX() によって左右どちらほフリックしたかを確認しており、絶対値で移動距離を確認できます。

ViewSwitcher の画面が変わる時のアニメーションは、setInAnimation と setOutAnimation で Android で定義されているフェードイン・フェードアウトを使用しています

通常、初期画面は setContentView(R.layout.activity_main); で作成されますが、ここでは画面の意味を明確にする為に、LayoutInflater で全ての画面( View ) のインスタンスを作成しています

MainActivity
package sample.lightbox.viewswitch;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ViewSwitcher;

public class MainActivity extends Activity  {

	private ViewSwitcher vs = null;

	// https://developer.android.com/training/gestures/detector.html
	private GestureDetector mDetector;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// 画面インスタンス作成用のオブジェクトをシステムから取得
		LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);

		// メイン画面定義のインスタンスを作成して表示する
		// http://y-anz-m.blogspot.jp/2012/04/android-viewgroup.html
		RelativeLayout root = (RelativeLayout) inflater.inflate(R.layout.activity_main, null);
		setContentView(root);
//		setContentView(R.layout.activity_main);

		// 戻るボタンの処理
		findViewById(R.id.button_p).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				vs.showPrevious();
			}
		});
		// 進むボタンの処理
		findViewById(R.id.button_n).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				vs.showNext();
			}
		});

		// レイアウト用の XML より View のインスタンスを作成
		// ( inflate( id, null ) では、ルートのクラスのインスタンスとなる  )
		LinearLayout image1 = (LinearLayout) inflater.inflate(R.layout.image_1, null);
		LinearLayout image2 = (LinearLayout) inflater.inflate(R.layout.image_2, null);

		// ViewSwitcher に 作成した View を追加する
		vs = (ViewSwitcher) root.findViewById(R.id.viewSwitcher);
		vs.addView(image1);
		vs.addView(image2);
		// アニメーションの設定
		vs.setInAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_in));
		vs.setOutAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_out));

		mDetector = new GestureDetector(MainActivity.this, new MyGestureListener());

	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// この処理で、タッチイベントからジェスチャーが処理できるようになる
		mDetector.onTouchEvent(event);
		return super.onTouchEvent(event);
	}

	// フリックによる画面切り替えの為の定義
	class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
		private static final String DEBUG_TAG = "Gestures";

		@Override
		public boolean onDown(MotionEvent event) {
			Log.i(DEBUG_TAG, "onDown: " + event.toString());
			return true;
		}

		@Override
		public boolean onFling(MotionEvent event1, MotionEvent event2,
							   float velocityX, float velocityY) {
			vs.showNext();
			Log.i("DEBUG_TAG", (event2.getX() - event1.getX() )+"" );
			return true;
		}
	}
}


activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin"
                android:paddingBottom="@dimen/activity_vertical_margin"
                tools:context=".MainActivity">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/buttons">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="戻る"
            android:id="@+id/button_p"
            android:layout_weight="1"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="進む"
            android:id="@+id/button_n"
            android:layout_weight="1"/>
    </LinearLayout>

    <ViewSwitcher
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/viewSwitcher"
        android:layout_below="@+id/buttons"/>
</RelativeLayout>


image_1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/imageView"
        android:src="@drawable/kirin"/>
</LinearLayout>
image_2.xml は image_1.xml をコピーして画像を変更しています

参考ページ

Detecting Common Gestures

Android カスタム ViewGroup 用XMLのルートタグを merge にする



posted by lightbox at 2015-09-13 00:27 | Comment(0) | Android Studio 2 | このブログの読者になる | 更新情報をチェックする

2015年09月11日


Google+ に投稿するテキスト内の文字列を太字(ボールド)にしたりイタリックにしたりする方法







アスタリスクで文字列を挟むと*太字*になりますが、
アスタリスクの両端は *スペース* が必要です

イタリックには、アンダーバーを使用しますが、
日本語は _italic にならない_ ようです

どちらが外側でもいいですが、 _*italicと太字*_ は同時に利用可能です

取り消し線はハイフンを使用します
あああ -あああ- あああ

ボールドにしたい文字列を *(アスタリスク) で挟み、イタリックにしたい文字列を _(アンダーバー)で挟み、取り消し線を設定したて文字列を-(ハイフン)で挟みます。

※ * と _ と - の両外側にはスペースが必要なようです

公式での表記( 『投稿文の書式を設定する』を開いて下さい )



posted by lightbox at 2015-09-11 14:08 | Google | このブログの読者になる | 更新情報をチェックする

2015年09月06日


ViewFlipper(複数ビュー) と ViewSwitcher(2つまでのビュー)


ViewFlipper
(a:ViewSwitcher)
(b:ViewSwitcher)


基本的にどちらも同じですが、オプションとしての画面は ViewSwitcher で十分なのでこのような構成が現実的だと思います。

主な特記事項

ViewFlipper の 移動イベントは、どちらも MainActivity に implements View.OnClickListener する事によって、MainActivity 内のイベントとして処理しています。ボタンが複数ありますが、一つのイベントとして処理されるので、アニメーションの設定を両方に同じものを設定して簡潔になっています。

フェードインとフェードアウトのイベントは、Android に定義されているものと、ユーザ定義のものを両方使っています。どちらも定義上は大差無いのでほぼ同じ効果になります。ただ、ヨーザ定義は変更する事によって自由にアニメーションをカスタマイズできます。

メインの移動処理では、スライドインとスライドアウトを使用していますが、Android が定義しているのは片方向のみです。showPrevious に合わせた逆スライドは(必要であれば)ユーザ定義する必要があります。
package sample.lightbox.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.ViewFlipper;
import android.widget.ViewSwitcher;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;

public class MainActivity extends Activity implements View.OnClickListener {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// MainActivity 内でリスナーを作成( implements View.OnClickListener )
		MainActivity.this.findViewById(R.id.mainPrevious).setOnClickListener(this);
		MainActivity.this.findViewById(R.id.mainNext).setOnClickListener(this);

		// ViewSwitcher 内のボタン( 最初の View )
		MainActivity.this.findViewById(R.id.switcherButton1).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				ViewSwitcher vs = (ViewSwitcher) MainActivity.this.findViewById(R.id.viewSwitcher);
				// Android の アニメーションを使用
				vs.setInAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_in));
				vs.setOutAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_out));
				vs.showNext();
			}
		});
		// ViewSwitcher 内のボタン( 次の View )
		MainActivity.this.findViewById(R.id.switcherButton2).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				ViewSwitcher vs = (ViewSwitcher) MainActivity.this.findViewById(R.id.viewSwitcher);
				// ユーザ作成 の アニメーションを使用
				vs.setInAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.in_effect));
				vs.setOutAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.out_effect));
				vs.showPrevious();
			}
		});

	}

	@Override
	public void onClick(View v) {

		// アニメーション設定
		ViewFlipper vf = (ViewFlipper) MainActivity.this.findViewById(R.id.viewFlipper);
		// Android の アニメーションを使用
		vf.setInAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.slide_in_left));
		vf.setOutAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.slide_out_right));

		// 使用されたボタンの id を取得
		int id = v.getId();

		if (id == R.id.mainPrevious) {
			vf.showPrevious();
		}
		if (id == R.id.mainNext) {
			vf.showNext();
		}

	}

}


画面定義
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/buttons"
        android:focusableInTouchMode="true">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="前へ移動"
            android:id="@+id/mainPrevious"
            android:layout_weight="1"
            android:layout_marginLeft="10dp" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="次へ移動"
            android:id="@+id/mainNext"
            android:layout_weight="1"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="10dp" />
    </LinearLayout>

    <ViewFlipper
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/viewFlipper"
        android:layout_below="@+id/buttons" >

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/imageView"
                android:src="@drawable/animal_mark_kirin" />
        </LinearLayout>

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/imageView2"
                android:src="@drawable/microphone1_boy" />
        </LinearLayout>

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/imageView3"
                android:src="@drawable/present_usagi" />
        </LinearLayout>

        <ViewSwitcher
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/viewSwitcher" >

            <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center">

                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="ViewSwitcher内ボタン"
                    android:id="@+id/switcherButton1" />
            </LinearLayout>

            <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <Button
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="ViewSwitcher内ボタン"
                    android:id="@+id/switcherButton2" />

                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/imageView4"
                    android:src="@drawable/skea1" />
            </LinearLayout>
        </ViewSwitcher>

    </ViewFlipper>
</RelativeLayout>


in_effect.xml
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromAlpha="0"
    android:toAlpha="1.0"
    />

out_effect.xml
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromAlpha="1.0"
    android:toAlpha="0"
    />



posted by lightbox at 2015-09-06 00:17 | Comment(0) | Android Studio 2 | このブログの読者になる | 更新情報をチェックする

2015年09月05日


ListView を使った AlertDialog で SD カード内のファイルのパスを取得する



以前から思っていたのですが、変数に日本語を使うと内容を説明しやすいので主な変数を全て日本語にして、かつ、クラス変数で参照が容易になるようにした上で、メソッドの処理を引数を使うのでは無く、この変数で処理を明示するようにしてみました。

主な特記事項

SD カードにアクセスする為に、AndroidManifest.xml には android.permission.READ_EXTERNAL_STORAGE または、android.permission.WRITE_EXTERNAL_STORAGE を uses-permission に設定する必要があります。

Environment.getExternalStorageState() で、SD カードが使用可能かどうかをチェックしています

この場合のダイアログは、ダイアログ内をクリックする毎に表示する内容や処理が変わります。固定部分は、Activity の onCreate で定義していますが、その他の部分は loadFileDialog(ユーザー作成のメソッド) 内で毎回設定してから、show メソッドで表示を行います。

ダイアログは、フラグメント(DialogFragment)では無いのでデバイスが回転するとリセットされます
package sample.lightbox.filedialog;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.io.File;

public class MainActivity extends Activity {

	private String tag = null;
	private File SDカードディレクトリ = null;
	private File 現在のファイルオブジェクト = null;
	private String 現在のパス文字列 = null;
	private String[] フォルダとファイルの一覧 = null;
	private AlertDialog.Builder ファイルダイアログ = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// リソースよりデータを取得する
		tag = getResources().getString(R.string.app_name);

		// SDカードのパスを取得( Environment クラス )
		String 外部ストレージの状態 = Environment.getExternalStorageState();
		if (外部ストレージの状態.equals(Environment.MEDIA_MOUNTED)) {
			SDカードディレクトリ = Environment.getExternalStorageDirectory();
			現在のパス文字列 = SDカードディレクトリ.getAbsolutePath();
			Log.i(tag, 現在のパス文字列);
		}

		// ファイルダイアログの固定部分の定義
		ファイルダイアログ = new AlertDialog.Builder(MainActivity.this);
		ファイルダイアログ
				.setPositiveButton("キャンセル", null)
				.setNegativeButton("親フォルダ", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						if (現在のパス文字列.equals(SDカードディレクトリ.getAbsolutePath())) {
							// SDカードより上には移動しない
							return;
						}

						現在のファイルオブジェクト = 現在のファイルオブジェクト.getParentFile();
						現在のパス文字列 = 現在のファイルオブジェクト.getAbsolutePath();
						フォルダとファイルの一覧 = 現在のファイルオブジェクト.list();
						loadFileDialog();

					}
				});


		// ボタン(SDカード参照) のイベント
		MainActivity.this.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// ボタンクリックで表示する場合は、常に SDカードディレクトリから
				現在のファイルオブジェクト = SDカードディレクトリ;
				現在のパス文字列 = 現在のファイルオブジェクト.getAbsolutePath();
				フォルダとファイルの一覧 = 現在のファイルオブジェクト.list();
				loadFileDialog();

			}
		});
	}

	// ファイルダイアログの表示
	void loadFileDialog() {

		// ダイアログの作成と振る舞いの定義
		// ※ 注意 : フラグメントでは無いのでデバイスが回転するとリセットされます
		ファイルダイアログ
				.setTitle(現在のパス文字列)
				.setItems(フォルダとファイルの一覧, new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						// 選択したファイルのパスの作成
						StringBuffer 選択したファイルのパス = new StringBuffer(現在のパス文字列);
						選択したファイルのパス
								.append(File.separator)
								.append(フォルダとファイルの一覧[which]);
						File ワークファイルオブジェクト = new File(選択したファイルのパス.toString());

						if (ワークファイルオブジェクト.isFile()) {
							// ファイル名のみ の表示
							Toast.makeText(MainActivity.this, フォルダとファイルの一覧[which], Toast.LENGTH_SHORT).show();
						} else {
							現在のファイルオブジェクト = ワークファイルオブジェクト;
							現在のパス文字列 = 現在のファイルオブジェクト.getAbsolutePath();
							フォルダとファイルの一覧 = 現在のファイルオブジェクト.list();
							loadFileDialog();
						}
					}
				});

		ファイルダイアログ.show();
	}

}


画面定義
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="SDカード参照"
        android:id="@+id/button"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true" />

</RelativeLayout>



posted by lightbox at 2015-09-05 20:56 | Comment(0) | Android Studio 2 | このブログの読者になる | 更新情報をチェックする

2015年09月04日


Java : テキストファイルを読み込んで正規表現で置換

テキストファイルの一括読み込みが必要でしたが、結局一行づつ読み込んで結合するのがオーソドックスのようです。正規表現は、パターンが解っておれば、他の言語より解りやすいと思いました。
( ここでは、簡易的に String を結合していますが、本来は StringBufferStringBuilder を使用します )

パターンの意味

"max_execution_time\s*=\s*[^\n]*?\n"

max_execution_time で始まって、0個以上空白文字の次に = があって、その
次に0個以上空白文字があって、さらに改行以外の文字が0個以上あって改行で
終わる。
※ \s は空白文字です。その後に * が続くので、 \s* で0個以上の空白文字です

[^\n]*? の ? は一番短い一致ですが、この場合省略してもOKです。
[^\n]* が改行以外なので、かならず最短になります。

max_execution_time\s*=\s*\d+ を使うと、行の最後までを判断せずに
必要な部分のみを置換する事ができます
※ ここでは、(\d+) としてサブマッチで使っています
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Main {

	public static void main(String[] args) {
		Main thisClass = new Main();
		thisClass.testAction();
	}

	// メソッド
	void testAction() {
		MyTool out = new MyTool(">>>");
		out.println("処理開始");

		String textData = "";
		
		try {
			// 生のバイトのストリーム
			FileInputStream fis = new FileInputStream( "c:\\php\\php.ini" );
			// SHIFT_JIS として読み込む為の準備
			InputStreamReader isr = new InputStreamReader(fis, "Windows-31j");
			// 行単位で読み込む為の準備
			BufferedReader br = new BufferedReader(isr);
		
			String line_buffer = "";
			// BufferedReader は、readLine が null を返すと読み込み終了
			while ( null != (line_buffer = br.readLine() ) ) {
				textData += line_buffer + "\n";
			}
		
			// 閉じる
			br.close();
			isr.close();
			fis.close();
		}
		catch( Exception e ) {
			textData = e.toString();
		}
		
		// 置換対象の内容確認
		out.printlnTarget(textData);

		// その文字列のみの置換
		// ( = の前後に一つのスペースが入っていないと置換できません )
		String textData1 = textData.replace("max_execution_time = 30", "max_execution_time = 90");
		// 置換結果の確認
		out.printlnTarget(textData1);

		// その文字列と、行の終わりまでの置換
		Pattern regPat = Pattern.compile("max_execution_time\\s*=\\s*[^\\n]*?\\n");
		Matcher regMat = regPat.matcher(textData);
		String textData2 = regMat.replaceAll("max_execution_time = 90\n");
		// 置換結果の確認
		out.printlnTarget(textData2);

		out.println("処理終了");
	}

	// *****************************************************
	// 内部用クラス
	// *****************************************************
	class MyTool {

		private String mark = null;

		// コンストラクタ
		MyTool(String pm) {
			mark = pm;
		}

		public void println(String str) {
			System.out.println( this.mark + str );
		}
		
		public void printlnTarget(String text) {
			Pattern regPat = Pattern.compile("max_execution_time\\s*=\\s*(\\d+)");
			Matcher regMat = regPat.matcher(text);

			println( "サブマッチ数 : " + regMat.groupCount()+"" );
			// find を実行しないと、サブマッチを取得できない
			if (regMat.find()) {
				println( regMat.group(0) ); // マッチ全体
				println( regMat.group(1) );	// ここが数字部分
			}
			System.out.println();
			
		}

	}	
	
}



タグ:java 正規表現
posted by lightbox at 2015-09-04 02:57 | java : テキストファイル | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します


Windows
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

Android SDK ポケットリファレンス
改訂版 Webデザイナーのための jQuery入門
今すぐ使えるかんたん ホームページ HTML&CSS入門
CSS ドロップシャドウの参考デモ
Google Hosted Libraries
cdnjs
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり