スキップしてメイン コンテンツに移動

投稿

ラベル(Code Tips)が付いた投稿を表示しています

PHPでCSV形式でデータを出力するためのコード

PHPでCSVファイルを出力するためのコードサンプルです。 CsvWriterクラスが本体です。最低限のメソッドを定義してあるだけなので必要に応じて拡張してみてください。 Writerインタフェースを定義して、CsvWriterクラスのコンストラクタに渡して切り替えることで、出力方式を変更することができます。 CsvWriterクラス CSV形式で出力するための本体のクラスです。このクラスのコンストラクタにWriterインタフェースを実装したクラスを渡します。 <?php class CsvWriter { private Writer $writer; private $elements = []; public function __construct(Writer $writer) { $this->writer = $writer; } public function init() { $this->writer->init(); } public function appendValuesBySpecificOrder(array $values, $keys) { foreach ($keys as $key) { $this->appendEscaped($values[$key] ?? $default); } return $this; } public function appendValues(array $values) { foreach ($values as $value) { $this->appendEscaped($value); } return $this; } public function appendAsLine(array $values) { foreac

PHPのXMLReaderで発生したエラーをExceptionとしてキャッチする方法

PHPのXMLReaderの内部で発生したエラーは、Exceptionではないためtry~catchブロックで捕まえることができません。 Exceptionとして捕まえるためには、set_error_handlerを使って、自前でエラーをExceptionに変換して投げる必要があります。 下記のコードで実現できます。 <?php // operationにエラーを発生させる可能性のある処理ブロックを渡す。 function caputureNativeErrorAndThrowIt(callable $operation) { $errorReportingLevel = error_reporting(E_ALL); set_error_handler(function( int $serverity, string $message, string $file, int $line ): void{ throw new \ErrorException($message, 0, $serverity, $file, $line); }); try { $operation(); } finally { restore_error_handler(); error_reporting($errorReportingLevel); } } // 下記はcaputureNativeErrorAndThrowIt関数をXMLReaderで使用した場合の例です。 $path = 'path_to_invalid_xml_file'; $reader = new \XMLReader(); $reader->open($path); caputureNativeErrorAndThrowIt(function() use($reader){ try { while($reader->read()){ // do something } } finally{ $reader->close()

PHPで特定の時刻の差分を秒数で計算するプログラム

PHPで特定の時刻の差分を秒数で計算する方法は、いろいろ考えられますが、ここではDateTimeクラスを使った方法を紹介します。 <?php // $date1, $date2はDateTimeで受け入れられる時刻の文字列表現であればOKです。 function diffSeconds(string $date1, string $date2) { return (new DateTime($date1))->getTimestamp() - (new DateTime($date2))->getTimestamp(); } // 下記のようにして使います。 diffSeconds('2020-06-05 13:54:32', '2020-04-21 22:12:22');

PHPでメモリにバッファしながらファイルに書き込む方法

最近のディスクは高速なのであまりIO Waitを意識することは少なくなりましたが、書き込み速度の遅いディスク(書き込みのコマンドのコストが高い)に何度も書き込みを実行すると、書き込みのトータルの時間が長くなる場合があります。 この投稿では、PHP版の簡単な「なんちゃって」BufferedWriterクラスを書いてみました。 通常であれば単純にfile_put_contentsメソッドを使って下記のように書けば十分です。 file_put_contents($filename, $chunk, FILE_APPEND|LOCK_EX); しかし、大量のデータを何度も書き込む場合に、特にパフォーマンスの観点から下記の問題が出てきます。 file_put_contentsはfopenによるファイルオープン、書き込み、クローズを実行するので手軽ではありますが、書き込みのオーバーヘッドは高くなります。 file_put_contentsに限ったことではないが、メモリにある程度バッファしてから書き込むことで、書き込みの実行回数を減らすことでパフォーマンスを高めることができる(例: JavaのBufferedWriter)。 というわけで、上記の問題を解決すべく、PHP版「なんちゃって」BufferedWriterクラスを書いてみました。 <?php class BufferedStreamFileWriter { private $path; private $bufferSize = 0; private $bufferLimit; private $buffer = ''; // constructor内でfopen public function __construct($path, $bufferLimit, $mode='a') { $this->path = $path; $this->bufferLimit = $bufferLimit; $this->handle = fopen($path, $mode); } // このメ

PHPのlibxmlでのエラーの扱い方

PHPでXML形式のデータを扱うにはlibxmlライブライを使うことが一般的です。 libxml内でのエラー発生時の処理は、libxml_use_internal_errorsの設定で、下記の2通りの設定が可能です。 libxml_use_internal_errors(false): Exceptionとして投げる。 libxml_use_internal_errors(true): libxml_get_errors()で取得。※libxml_clear_errorsで事前にエラーをクリアしておく方が無難。 libxml_use_internal_errors(true)に設定して、Exceptionを発生させないようにする関数のサンプルを示します。 $excecutionに実際のXML処理を渡します。 function executeInLibXmlUseInternalErrors(callable $execution) { // 現在のlibxml_use_internal_errorsの設定を処理後に戻すために保存 $useErrors = libxml_use_internal_errors(); try {   libxml_clear_errors(); libxml_use_internal_errors(true); return $execution(); } finally{ // 処理が終わったらlibxml_use_internal_errorsの設定をもとに戻す libxml_use_internal_errors($useErrors); } } // 下記はXPathでDOMDodumentからXMLの要素を取得する場合の使用例です。 // XMLの処理中にもExceptionが発生しないので、プログラム内で処理することができます。 $xpath = '/xpath'; $file = '/path_to_xml_file'; $result = executeInLibXmlUseInternalErrors(function

register_shutdown_functionを使ってPHPのFatal Error発生後の処理を制御

PHP 7以降では、PHPのエラーは基本的にErrorクラスとして扱われ、try-catchブロックで捕まえることができるようになりました。(Catchable Fatal Error) ちなみにPHP 7では下記の2つのクラスがThrowableクラスを継承しており、両方捕まえるときは、try-catchブロックでThrowableをcatchするように書けばOKです。 Exception Error ただし、一部のFatal Error(例: Memory Exhausted Error)はtry-catchブロックで捕まえることができません。 Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 9792 bytes) in .... この場合は、register_shutdown_functionを使って、PHPのプログラムが終了したときにエラー処理をするしかなさそうです。 register_shutdown_functionとerror_get_lastを使ってエラー処理をする関数のコード例を示します。 <?php // PHPのError定数 => 文字列表現の連想配列 const ERROR_CODE_TO_STRING = [ E_ERROR => 'E_ERROR', E_WARNING => 'E_WARNING', E_PARSE => 'E_PARSE', E_NOTICE => 'E_NOTICE', E_CORE_ERROR => 'E_CORE_ERROR', E_CORE_WARNING => 'E_CORE_WARNING', E_COMPILE_WARNING => 'E_COMPILE_WARNING', E_USER_ERROR => 'E_USER_ERROR', E_USER_WARNING => '

MySQLでGROUP_CONCATしたフィールドに対して疑似的にLIMITを実現する方法

MySQLでGROUP_CONCATしたフィールドに対して疑似的にLIMITを実現するには、GROUP_CONCATで生成された文字列に対して、SUBSTRING_INDEXを使って文字列を切り出す方法が簡単です。 # 下記はid, codeをカラムに持つテーブルで、codeカラムでGROUP BYして、codeごとにidをlimitで取得する例です。 SELECT code ,SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY id DESC), ',', :limit) # :limitの部分に取得したい件数を指定。 FROM table GROUP BY code 長所は、下記のように条件を指定して、LIMIT句で取得件数を指定したクエリを何度も発行する必要がないところです。 特に、一回あたりクエリの発行コストが高い場合は、GROUP_CONCATを使って一度に取得したほうが最終的な実行時間をかなり節約することができます。 SELECT id FROM table WHERE code = 'A' ORDER BY id DESC LIMIT :limit; ただし、短所も多いので、使用する際は、これらの短所について十分に考慮したうえで使ってください。 GROUP_CONCATで生成された文字列に対して、SUBSTRING_INDEXを使って文字列を切り出すという文字列処理なので、無駄が多い。 特にGROUP_CONCATで生成された元の文字列が長い場合。 GROUP_CONCATの区切り文字が、GROUP_CONCATされる元の文字列に含まれていると正しくLIMITされない。 例:GROUP_CONCATされる元の文字列にカンマが含まれているのに、カンマを区切り文字で指定している場合。 GROUP_CONCATの最大文字数制限を超えた場合は、機能しない。 MySQLのGROUP_CONCATの最大文字数制限は、「SHOW VARIABLES LIKE '%group_concat%';」で調べられます。デフォルト値は1024のようです。

PHPで現在設定されているerror reporting levelを文字列で表示

PHPのerror reporting levelは、bit形式で表現されていて、error_reporting関数で取得しても、何が設定されているのかすぐにはわかりづらいと思います。 ちょっとしたプログラムですが、error_reporting_levelを文字列形式で出力するプログラムを書いてみました。 <?php class PHPUtils { private const ERROR_CODE_TO_STRING = [ E_ERROR => 'E_ERROR', E_WARNING => 'E_WARNING', E_PARSE => 'E_PARSE', E_NOTICE => 'E_NOTICE', E_CORE_ERROR => 'E_CORE_ERROR', E_CORE_WARNING => 'E_CORE_WARNING', E_COMPILE_WARNING => 'E_COMPILE_WARNING', E_USER_ERROR => 'E_USER_ERROR', E_USER_WARNING => 'E_USER_WARNING', E_USER_NOTICE => 'E_USER_NOTICE', E_STRICT => 'E_STRICT', E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', E_DEPRECATED => 'E_DEPRECATED', E_USER_DEPRECATED => 'E_USER_DEPRECATED', ]; public static function getCurr

PHPでZipファイルを作成

PHPでZipファイルを作成するためのコードです。 ZipArchive::openメソッドの第2引数のオプションで新規作成や既存Zipファイルへの追加をコントロールできます。 ZipArchive::openメソッドの戻り値をチェックすることで、openに成功したか失敗したかを確認することができます。 function createZipFile(string $zipFilePath, $targetFiles) { $zip = new \ZipArchive(); try { $zip->open($zipFilePath, \ZipArchive::CREATE|\ZipArchive::OVERWRITE); foreach($targetFiles as $path => $localName) { $zip->addFile($path, $localName); } } finally { $zip->close(); } }

Linuxでテキストファイルから重複行を取り除く方法

下記のコマンドで実現できます。 less {対象のテキストファイル} | sort -s -k 1 | uniq > result.txt コマンドの簡単な解説です。 lessコマンドで、対象のテキストファイルを読み込み sortコマンドで、1行目を指定してソート uniqコマンドで、重複を取り除く 結果をテキストに書き込み

PHPでZipファイルを解凍する方法

PHPでZipファイルを解凍するには、ZipArchiveを使うのが簡単です。パスワードの必要なZipファイルも簡単に解凍できます。 function unzipFile($source, $destination, $password=null) { $zip = new \ZipArchive(); try {   if(!$zip->open($source)) { throw new \RuntimeException('failed to open zip file: '.$source); } if($password) { $zip->setPassword($password); } $zip->extractTo($destination); } finally { $zip->close(); } }

MySQLで分散Transaction (XATrsancsaction)を使うためのPHPのサンプルコード

別サーバーにまたがる複数のDBへのTransactrionを管理するには、2 Phase Commitが用いられることがあります。 今回のコードは、できるだけ流れがわかるように可能な限り単純にしてあります。エラー処理などは厳密に実施していませんので注意してください。 その代わり1コマンドごとにログを書くようにして、エラーが起きたときにどこで落ちたか、可能な限り終えるようにしてあります。 このコードをProductionで使う場合(あまり推奨しません。。。)は、十分に検証してから使ってください。 XA Transactionのコマンドの流れ server1とserver2の2つのDBサーバーに対してXA transactionコマンドを実行する流れは、下記のようになります。 // XA trsanction start server1: XA start 'test' server2: XA start 'test' //-------------------------------- // server1とserver2のDBのデータ更新 //-------------------------------- // XA trsanction commit server1: XA END 'test' server2: XA END 'test' server1: XA PREPARE 'test' server2: XA PREPARE 'test' server1: XA COMMIT 'test' server2: XA COMMIT 'test' // 更新中にエラーが起きた場合のrollback server1: XA END 'test' server2: XA END 'test' server1: XA PREPARE 'test' server2: XA PREPARE 'test' server1: XA ROLLBACK 'test' server2: XA ROLLBACK 'test&

PHPでCurlを使ってファイルをダウンロード

PHPでcurlを使ってネットワーク上からファイルをダウンロードするサンプルコードです。 用途に応じてカスタマイズして使ってみてください。 Curlの実行クラス(メモリ上に展開とファイルに直接ダウンロードするメソッド) <?php namespace Util\Net; class Curl { // 引数の$optionsで設定をカスタマイズ可能 public static function request($url, $options): CurlResponse { return self::execCrul($url, $options + [ CURLOPT_HEADER => false, CURLOPT_RETURNTRANSFER => true, // 例: 5回までリダイレクト許可 CURLOPT_FOLLOWLOCATION => true, CURLOPT_MAXREDIRS => 5, // 例: タイムアウト3秒 CURLOPT_TIMEOUT => 3, CURLOPT_CONNECTTIMEOUT=> 3, // 例: sslのエラーを無視 (安全性下がるのでよくない) CURLOPT_SSL_VERIFYHOST => false, CURLOPT_SSL_VERIFYPEER => false, ]); } // curlの実行結果を直接ファイルにダウンロードする public static function downloadAsFile($url, $storePath, $options): CurlResponse { $fp = fopen($storePath, 'w+');

Amazon Product Advertising API 5.0のJavaのサンプルコード

Amazon Product Advertising APIがjsonベースの5.0に移行することが発表されました。 Amazonが提供しているSDKを利用していない場合は、APIのリクエストのインターフェースがXMLからJSONに変わるので、コードの書き換えは結構面倒です。 Amazonの公式ページ でもSDKを使用しないバージョンのサンプルコードが公開されていますが、ApacheのHttpComponentsのライブラリとjsonのライブラリが依存関係に含まれていたので、とにかくAPIを動かしてみたい人向けに 標準のJDKだけで動作するサンプルコードを書きました。 (ただし実運用ではJacksonやGSONなど、何らかのjsonライブラリは必須です。) package com.dukesoftware.amazon; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; // Java8で動くように、あえてvarなどのJava8では使えないJava機能は未使用 // スクラッチパッドを使うと便利 // https://webservices.amazon.co.jp/paapi5/scratchpad/ public class AmazonProductAdvertisingApiV5 { public static void main(String[] args) { // request生成部分はJacksonやGSONなどのライブラリを使用するのが現実的 String jsonRequest = "{"

Java: Identify Country From IP Address

Identify Country From IP Address Many people sometimes would like to identify country from IP address when you check access log or something. Most of the people google with keywords like "ip address country" or "whois ip" or something, and then use the internet service which they find. In this post, I will show you program for identifying country from IP address. I wrote the program in Java, but if you an average developer you can easily translate into the program language you prefer. Using File Provided by RIR IP address is allocated, registered and managed by regional internet registry ( RIR ). There are five organization based on covering region: African Network Information Centre (AfriNIC): Africa American Registry for Internet Numbers (ARIN): the United States, Canada, several parts of the Caribbean region, and Antarctica. Asia-Pacific Network Information Centre (APNIC): Asia, Australia, New Zealand, and neighboring countries Latin America and

Java: Coloned IPv6 Address To BigInteger

IPv6 Address to Long I have written code for converting coloned IPv6 IP address to BigInteger value in Java. I have already written similar code for IPv4 IP address (see this post ). The function is useful when you compare IP addresses based on numeric magnitude relationship. Java Code public static BigInteger colonIpV6_to_BigInteger(String colonedIP) { String[] addrArray = colonedIP.split(":", -1); BigInteger num = BigInteger.ZERO; BigInteger block = BigInteger.valueOf(65536); for (int i = 0; i < addrArray.length; i++) { if(!addrArray[i].equals("")) { int power = 8-i; BigInteger value = BigInteger.valueOf(Long.parseLong(addrArray[i], 16) % 65536L); value = value.multiply(block.pow(power)); num = num.add(value); } } return num; } Here is an example. // following code output "22170076769632982771575277020213308075606016"

Java: Dotted IPv4 Address To BigInteger

IPv4 Address to Long I have written code for converting dotted IPv4 IP address to BigInteger value in Java. This code is inspired by PHP's ip2long function. The function is useful when you compare IP addresses based on numeric magnitude relationship. Java Code public static BigInteger dotIPv4_to_BigInteger(String dottedIP) { String[] addrArray = dottedIP.split("\\."); BigInteger num = BigInteger.ZERO; BigInteger block = BigInteger.valueOf(256); for (int i = 0; i < addrArray.length; i++) { int power = 3-i; BigInteger value = BigInteger.valueOf(Integer.parseInt(addrArray[i]) % 256); value = value.multiply(block.pow(power)); num = num.add(value); } return num; } Here is an example. // following code output "2071690107" System.out.println(dotIPv4_to_BigInteger("123.123.123.123"));

PHP: Execute Any DB Access Code in Transaction

Reusable Code for Execute Any DB Access Code in Transaction In this post, I will show you highly reusable utility code for wrapping and executing original db access code in transaction. Anyway let's show you the code. function executeInTransaction(callable $func) { $conn = new PDO(SERVER_NAME, USERNAME, PASSWORD, DBNAME); try { $conn->beginTransaction(); $func($conn); $conn->commit(); } catch (Exception $ex) { $conn->rollBack(); throw $ex; } } Oh, how to use? You just simply passing your core DB access code as the callable $func argument. Okay, let me show you example in next section. Example Usage First, assume you have following 2 methods for inserting data to DB. CONST SERVER_NAME = 'localhost'; CONST USERNAME = "username"; CONST PASSWORD = "password"; CONS

Java: Compute Source Code Similarity Based on Jaccard Similarity Coefficient

Compute Source Code Similarity I have tried to analyze source code by various methods recently. In this post, I will show you my artifact - Compute source code similarity based on Jaccard Similarity Coefficient. Jaccard Similarity Coefficient is an common and quick techniqueto compute similarity between 2 documents. You can see more details in Jaccard index or MinHash . My similarity computation strategy is below: Calculate hash value for each line for each files. Create set which contains hashes calculated in the above process for the each files. Compute Jaccard Similarity Coefficient for all combinations of the files. Source Code Now I can show you code snippets for compute source code similarity based on Jaccard Similarity Coefficient. Jaccard Simlarity package com.dukesoftware.utils.text; import java.util.HashSet; import java.util.Set; /** * Jaccard similarity coefficient http://en.wikipedia.org/wiki/MinHash */ public class JaccardSimlarity<T> { priv

Java 8: Process Each Line in File

Here is the code for iterating each line in file. You simply write lambda expression for processing line and doing something nice. private static void processLine(File file, Consumer<String> lineProcessor) throws IOException{ try(FileReader in = new FileReader(file); BufferedReader br = new BufferedReader(in)){ String line; while ((line = br.readLine()) != null) { lineProcessor.accept(line); } } } The below code is an example usage of processLine method. The code simply print out lines in file. public static void main(String[] args) throws IOException { processLine(new File("c:/temp/test.txt"), System.out::println); }