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

ActionScript 3.0: Hit Youtube API

I wrote a tiny program for getting Youtube video information by hitting Youtube API in ActionScript 3.0.
Some generic classes or methods might be missing but I think you can easily guess what they are doing and can add them easily yourself.

Example Usage

Ok, starting from the example usage.
package utils.video 
{
    import flash.display.Sprite;
    import utils.file.SyncFileSaveDownLoader;
    import utils.ITaskProgressCounter;
    import utils.TaskProgressCounter;
    import utils.video.youtube.YoutubeAPI;
    import utils.video.YoutubeFLVURLGetEvent;
    import utils.video.youtube.YoutubeLocalCacheManager;
    import utils.video.youtube.YoutubeVideoEntryDispatcher;
    import utils.video.youtube.YoutubeVideoEntryEvent;

    public class Tester extends Sprite
    {
        private    var downloader:SyncFileSaveDownLoader = new SyncFileSaveDownLoader();
        private var youtubeLocalCacheManager:YoutubeLocalCacheManager =  new YoutubeLocalCacheManager("c:\\temp\\youtube", downloader);
        
        public function Tester() 
        {
            var dispatcher:YoutubeVideoEntryDispatcher = new YoutubeVideoEntryDispatcher();
            dispatcher.addEventListener(YoutubeVideoEntryEvent.CREATED, created);
            
            var api:YoutubeAPI = new YoutubeAPI("utf-8", dispatcher);
            
            api.searchByKeywords(10, "Google IO");
            
            // directtly hitting api
            // api.exec("http://gdata.youtube.com/feeds/videos?start-index=1&max-results=25", 2);
            // api.exec("http://gdata.youtube.com/feeds/users/youtube/uploads?start-index=1&max-results=25", 2);
        }
        
        public function created(evt:YoutubeVideoEntryEvent):void {
             // debug print
            trace("---");
            trace(evt.videoEntry.author.name);
            trace(evt.videoEntry.playerURL);
            
            // download thumbnails
            youtubeLocalCacheManager.downloadThumbnails(evt.videoEntry);
        }
   }
    
}


Main Classes

package utils.video.youtube
{
    import flash.net.URLLoader;
    import flash.net.URLLoaderDataFormat;
    import flash.events.Event;
    import flash.events.TimerEvent;
    import flash.net.URLRequest;
    import flash.events.ProgressEvent;
    import flash.utils.ByteArray;
    import utils.StringUtils;
    import utils.tool.ByteLoadHelper;
    import utils.tool.ByteLoadEvent;

    public class YoutubeAPI
    {
        private var charEncode:String;
        private var videoParser:YoutubeVideoEntryParser;
            
        private var baseURL:String = "http://gdata.youtube.com/feeds/videos/";
        
        public static const NS_ATOM:Namespace = new Namespace("", "http://www.w3.org/2005/Atom");
        public static const NS_MEDIA:Namespace = new Namespace("media","http://search.yahoo.com/mrss/");
        public static const NS_GD:Namespace = new Namespace("gd","http://schemas.google.com/g/2005");
        public static const NS_YT:Namespace = new Namespace("yt","http://gdata.youtube.com/schemas/2007");
        public static const Q_ENTRY:QName = new QName(NS_ATOM, "entry");    
        public static const Q_LINK:QName = new QName(NS_ATOM, "link");
        
        public function YoutubeAPI(charEncode:String, videoParser:YoutubeVideoEntryParser) 
        {
            this.charEncode = charEncode;
            this.videoParser = videoParser;
        }
        
        public function searchByKeywords(max:int, ...args):void {
            var queryStr:String = StringUtils.concatAllAsString("+", args);
            if(queryStr.length > 0){
                exec(baseURL + "?vq=" + queryStr, max);
            }
        }
        
        public final function exec(url:String, max:int):void
        {
            var loader:ByteLoadHelper = new ByteLoadHelper();
            loader.addEventListener(ByteLoadEvent.COMPLETE, completeHandler);
            loader.load(url);
            
            var maxInit:uint = max;

            function completeHandler(evt:ByteLoadEvent):void {
                loader.removeEventListener(ByteLoadEvent.COMPLETE, completeHandler);
                var bytes:ByteArray = evt.data;
                var rss:String = bytes.readMultiByte(bytes.bytesAvailable, charEncode);
                var xml:XML = new XML(rss);
                
                for each(var entryXML:XML in xml.child(Q_ENTRY)) {
                    if (max <= 0) {
                        return;
                    }
                    
                    try {
                        videoParser.parse(entryXML);
                    }
                    catch (e:TypeError) {
                        // should so proper error handling
                        trace(e);
                    }
                    max--;
                }
                
                if(maxInit > 0){
                    var linkNext:XMLList = xml.child(Q_LINK).(attribute("rel") == "next");
                    for each(var elemXML:XML in linkNext) {
                        exec(elemXML.attribute("href"), maxInit);
                    }
                }
            }
        }
    }
    
}
package utils.video.youtube 
{
    import flash.events.EventDispatcher;

    public class YoutubeVideoEntryDispatcher extends EventDispatcher implements YoutubeVideoEntryParser
    {
        private var factory:YoutubeVideoEntryFactory;
        
        public function YoutubeVideoEntryDispatcher() 
        {
            this.factory = new YoutubeVideoEntryFactory();
        }
    
        public function parse(entryXML:XML):void {
            dispatchEvent(new YoutubeVideoEntryEvent(factory.create(entryXML), YoutubeVideoEntryEvent.CREATED));
        }
    }
    
}
package utils.video.youtube 
{
    import utils.StringUtils;
    import utils.video.ThumbnailInfo;
    
    public class YoutubeVideoEntryFactory
    {
        
        public function YoutubeVideoEntryFactory() 
        {
            
        }
        
        public function create(entryXML:XML):YoutubeVideoEntry {
            var entry:YoutubeVideoEntry = new YoutubeVideoEntry();
            
            var authorList:XMLList = entryXML.child(new QName(YoutubeAPI.NS_ATOM, "author"));
            entry.author = new YoutubeAuthor(
                authorList.child(new QName(YoutubeAPI.NS_ATOM, "name")),
                authorList.child(new QName(YoutubeAPI.NS_ATOM, "uri"))
            );

            var idList:XMLList = entryXML.child(new QName(YoutubeAPI.NS_ATOM, "id"));
            var idURL:String = idList.toString();
            var id:String = StringUtils.extractLast(idURL, "/");
            entry.id = id;
            
            var mediaGroupList:XMLList = entryXML.child(new QName(YoutubeAPI.NS_MEDIA, "group"));
            for each(var mediaGroup:XML in mediaGroupList) {
                for each(var elemXML:XML in mediaGroup.child(new QName(YoutubeAPI.NS_MEDIA, "player")).attribute("url")) {
                    entry.playerURL = elemXML.toString();
                }

                for each(elemXML in mediaGroup.child(new QName(YoutubeAPI.NS_MEDIA, "keywords"))) {
                    var keywords:String = elemXML.toString();
                    var tags:Array = keywords.split(",");
                    for each(var tag:String in tags ) {
                        entry.tags.push(StringUtils.trim(tag));
                    }
                }
                
                for each(elemXML in mediaGroup.child(new QName(YoutubeAPI.NS_MEDIA, "title"))) {
                    entry.title = elemXML.toString();
                }

                var categoryList:XMLList = mediaGroup.child(new QName(YoutubeAPI.NS_MEDIA, "category")).(hasOwnProperty("@label"));
                for each(elemXML in categoryList) {
                    entry.category = elemXML.toString();
                }

                for each(elemXML in mediaGroup.child(new QName(YoutubeAPI.NS_MEDIA, "description"))) {
                    entry.description = elemXML.toString();
                }

                for each(elemXML in mediaGroup.child(new QName(YoutubeAPI.NS_MEDIA, "thumbnail"))) {
                    entry.thumbnails.push(new ThumbnailInfo(
                        id,
                        elemXML.attribute("url").toString(), 
                        int(elemXML.attribute("width")), 
                        int(elemXML.attribute("height").toString()), 
                        decodeTimeStrToSec(elemXML.attribute("time").toString())
                    ));
                }
            }
                                    
            for each(elemXML in entryXML.child(new QName(YoutubeAPI.NS_GD, "rating"))) {
                entry.rating = new YoutubeRating(
                    int(elemXML.attribute("min")), 
                    int(elemXML.attribute("max")), 
                    int(elemXML.attribute("numRaters")), 
                    Number(elemXML.attribute("average"))
                );
            }
            
            for each(elemXML in entryXML.child(new QName(YoutubeAPI.NS_YT, "statistics"))) {
                entry.statistics = new YoutubeStatistics(
                    int(elemXML.attribute("viewCount")), 
                    int(elemXML.attribute("favoriteCount"))
                );
            }
            return entry;
        }
            
        public static function decodeTimeStrToSec(time:String):uint {
            var splitted:Array = time.split(":");
            return uint(splitted[0]) * 3600 + uint(splitted[1]) * 60 + uint(splitted[2]);
        }
    }

    
}
package utils.video.youtube 
{
    import flash.filesystem.File;
    import utils.file.IDownloader;
    import utils.Utils;
    import utils.video.IFlvUrlGetter;
    import utils.video.ThumbnailInfo;
    
    public class YoutubeLocalCacheManager 
    {
        private var _downloader:IDownloader;
        private var _baseDir:String 
        
        public function YoutubeLocalCacheManager(baseDir:String, downloader:IDownloader) 
        {
            this._downloader = downloader;
            this._baseDir = baseDir;
        }
        
        protected function getDir(entry:YoutubeVideoEntry):File {
            var id:String = entry.id;
            var dir:File = new File(_baseDir + File.separator + id);
            if (!dir.exists) {
                dir.createDirectory();
            }
            return dir;
        }
        
        
        public function downloadThumbnails(youtubeEntry:YoutubeVideoEntry):void {
            for each(var thumb:ThumbnailInfo in youtubeEntry.thumbnails) {
                var fileName:String = Utils.getFileName(thumb.url, "/");
                var path:String = getDir(youtubeEntry).nativePath + File.separator + fileName;
                if(!new File(path).exists){
                    _downloader.download(thumb.url, path);
                }
            }
        }
    }
    
}


Event Classes

package utils.video.youtube 
{
    import flash.events.Event;
    
    public class YoutubeVideoEntryEvent extends Event 
    {
        public static const CREATED:String = "youutbe_video_entry_created";
        
        private var _videoEntry:YoutubeVideoEntry;
        
        public function YoutubeVideoEntryEvent(videoEntry:YoutubeVideoEntry, type:String, bubbles:Boolean=false, cancelable:Boolean=false) 
        { 
            super(type, bubbles, cancelable);
            this._videoEntry = videoEntry;
            
        } 
        
        public override function clone():Event 
        { 
            return new YoutubeVideoEntryEvent(_videoEntry, type, bubbles, cancelable);
        } 
        
        public override function toString():String 
        { 
            return formatToString("YoutubeVideoEntryEvents", "type", "bubbles", "cancelable", "eventPhase"); 
        }
        
        public function get videoEntry():YoutubeVideoEntry {
            return _videoEntry;
        }
        
    }
    
}


Data Object Classes

Nothing special... :) simply flattened xml object to classes (we can able to use more common library to mapping between class and xml).
package utils.video.youtube
{
    import utils.TaggableEntry;
    import utils.video.ThumbnailInfo;

    public class YoutubeVideoEntry
    {
        private var _tags:Vector.<String> = new Vector.<String>();

        private var _id:String;
        private var _playerURL:String;
        private var _thumbnails:Vector.<ThumbnailInfo>;
        private var _rating:YoutubeRating;
        private var _description:String;
        private var _statistics:YoutubeStatistics;
        private var _author:YoutubeAuthor;
        private var _category:String;
        private var _title:String;
        
        public function YoutubeVideoEntry() 
        {
            this._thumbnails = new Vector.<ThumbnailInfo>();
        }
        
        public function set id(id:String):void {
            this._id = id;
        }

        public function get id():String {
            return _id;
        }

        public function set playerURL(url:String):void {
            this._playerURL = url;
        }
        
        public function get playerURL():String {
            return _playerURL;
        }
        
        public function get thumbnails():Vector.<ThumbnailInfo> {
            return _thumbnails;
        }
        
        public function set rating(rate:YoutubeRating):void {
            this._rating = rate;
        }

        public function get rating():YoutubeRating {
            return _rating;
        }

        public function set description(description:String):void {
            this._description = description;
        }
        
        public function get description():String {
            return _description;
        }
        
        public function set statistics(statistics:YoutubeStatistics):void {
            this._statistics = statistics;
        }
        
        public function get statistics():YoutubeStatistics {
            return this._statistics;
        }
        
        public function set author(author:YoutubeAuthor):void {
            this._author = author;
        }
        
        public function get author():YoutubeAuthor {
            return this._author;
        }
        
        public function set category(category:String):void {
            this._category = category;
        }
        
        public function get category():String {
            return this._category;
        }
        
        public function set title(title:String):void {
            this._title = title;
        }
        
        public function get title():String {
            return this._title;
        }
        
        public function get key():String {
            return id;
        }
            
        public function get tags():Vector.<String> {
            return _tags;
        }    
    }
    
}
package utils.video.youtube
{

    public class YoutubeAuthor 
    {
        
        private var _name:String;
        private var _uri:String;
        
        public function YoutubeAuthor(name:String, uri:String) 
        {
            this._name = name;
            this._uri = uri;
        }
        
        public function get name():String {
            return _name;
        }

        public function get uri():String {
            return _uri;
        }
        
    }
    
}
package utils.video.youtube
{
    public class YoutubeRating 
    {
        private var _max:int, _min:int, _numRaters:int, _average:Number;
        
        public function YoutubeRating(max:int, min:int, numRaters:int, average:Number) 
        {
            this._max = max;
            this._min = min;
            this._numRaters = numRaters;
            this._average = average;
        }
        
        public function get max():int {
            return _max;
        }

        public function get min():int {
            return _min;
        }

        public function get numRaters():int {
            return _numRaters;
        }


        public function get average():Number {
            return _average;
        }
        
    }
    
}
package utils.video.youtube
{
    public class YoutubeStatistics 
    {
        private var _viewCount:int;
        private var _favoriteCount:int;
        
        public function YoutubeStatistics(viewCount:int, favoriteCount:int) 
        {
            this._viewCount = viewCount;
            this._favoriteCount = favoriteCount;
        }
        
        public function get favoriteCount():int
        {
            return _favoriteCount;
        }
        
        public function get viewCount():int {
            return _viewCount;
        }
        
    }
    
}


Helper Classes

Mainly class for downloading resources.
You can downsize this class if you need. I think a bit too much for this youtube example :P
package utils.file
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.events.SecurityErrorEvent;
    import flash.net.URLLoader;
    import flash.net.URLLoaderDataFormat;
    import flash.net.URLRequest;
    import utils.IOUtils;
    
    public class SyncFileSaveDownLoader extends EventDispatcher implements IDownloader
    {
        private var id:int;
        
        public function SyncFileSaveDownLoader() 
        {
            this.id = 0;
        }
        
        public function download(url:String, path:String, listenProgress:Boolean=false):FileDownloadTask {
            var loader:URLLoader = new URLLoader();
            var task:FileDownloadTask = new FileDownloadTask(id.toString(), url, path, loader);
            
            loader.dataFormat = URLLoaderDataFormat.BINARY;
            loader.addEventListener(Event.COMPLETE, completeHandler);
            loader.addEventListener(IOErrorEvent.IO_ERROR, ioEllorHandler);
            if(listenProgress){
                loader.addEventListener(ProgressEvent.PROGRESS, handleProgress);
            }
            loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
            loader.load(new URLRequest(url));
            id++;
            return task;
            
            function handleProgress( pevt:ProgressEvent ):void {
                var total:Number = pevt.bytesTotal;
                if (total != 0) {
                    task.totalBytes = total;
                    task.percentage = Math.round( pevt.bytesLoaded / total * 100 );
                    task.status = FileDownloadTask.DOWNLOADING;
                }
            }
            
            function completeHandler(cevt:Event):void
            {
                saveByteData(cevt.target.data, path);
                task.status = FileDownloadTask.SUCCESS;
                finalize();
            }

                    
            function securityErrorHandler(e:SecurityErrorEvent):void 
            {
                task.status = FileDownloadTask.FAIL;
                finalize();
            }
            
            function ioEllorHandler(e:IOErrorEvent):void 
            {
                task.status = FileDownloadTask.FAIL;
                finalize();
            }
            
            function finalize():void {
                loader.removeEventListener(Event.COMPLETE, completeHandler);
                loader.removeEventListener(ProgressEvent.PROGRESS, handleProgress);
                loader.removeEventListener(IOErrorEvent.IO_ERROR, ioEllorHandler);
                loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
                task.dispose();
            }

        }

        public static function saveByteData(data:ByteArray, path:String):void {
            try {
                var file:File = new File(path);
                var fs:FileStream = new FileStream();
                fs.open(file, FileMode.WRITE);
                fs.writeBytes(data);
                fs.close();
            }
            catch (err:IOError) {
                trace(err);
            }
        }
    }
    
}
package utils.file 
{
    import flash.events.Event;
    
    public class FileDownloadEvent extends Event 
    {
        public static const SAVE_CONPLETE:String = "SaveComplete";
        
        private var _url:String;
        private var _path:String;
        
        public function FileDownloadEvent(url:String, path:String, type:String, bubbles:Boolean=false, cancelable:Boolean=false) 
        { 
            super(type, bubbles, cancelable);
            this._url = url;
            this._path = path;
        } 
        
        public override function clone():Event 
        { 
            return new FileDownloadEvent(_url, _path, type, bubbles, cancelable);
        } 
        
        public override function toString():String 
        { 
            return formatToString("FileDownloadEvent", "type", "bubbles", "cancelable", "eventPhase"); 
        }
        
        public function get url():String {
            return _url;
        }
        
        public function get path():String {
            return _path;
        }
    }
    
}
package utils.file 
{
    import flash.net.URLLoader;
    
    public class FileDownloadTask
    {
        public static const DOWNLOADING:String = "Downloading";
        public static const SAVING:String = "Saving";
        public static const SUCCESS:String = "Success";
        public static const FAIL:String = "Fail";
        
        private var _id:String;
        private var _url:String;
        private var _path:String;
        private var _status:String;
        
        private var _percentage:Number;
        private var _totalBytes:Number;
        private var _urlLoader:URLLoader;
        
        public function FileDownloadTask(id:String, url:String, path:String, urlLoader:URLLoader) 
        {
            this._id = id;
            this._url = url;
            this._path = path;
            this._urlLoader = urlLoader;
        }
        
        public function get url():String { return _url; }
        
        public function get id():String { return _id; }
        
        public function get path():String { return _path; }
        
        public function set status(status:String):void {
            if (status != DOWNLOADING && status != SUCCESS && status != FAIL && status != SAVING) {
                throw new Error("Invalid Status");
            }
            this._status = status;
        }
        
        public function get status():String {
            return _status;
        }
        
        public function cancel():void {
            if (_urlLoader != null) {
                _urlLoader.close();
                _urlLoader = null;
            }
        }
        
        public function dispose():void {
            _urlLoader = null;
        }
        
        public function get percentage():Number { return _percentage; }
        
        public function set percentage(value:Number):void 
        {
            _percentage = value;
        }
        
        public function get totalBytes():Number { return _totalBytes; }
        
        public function set totalBytes(value:Number):void 
        {
            _totalBytes = value;
        }
        
    }
    
}

コメント

このブログの人気の投稿

Eclipseでコードカバレッジのハイライトを削除する方法

Eclipseには便利なコードカバレッジ表示機能が搭載されていますが、コード内に緑、赤、黄の色付けがされて煩く感じるときもあると思います。 1度カバレッジの色付けが出てしまった後に消す方法の紹介です(方法は簡単)。 下記のキャプチャの青いマーカーで示した「Remove All Sessions」のボタンを押せばすべて消えます。

「特定の文字から始まらない文字列」にマッチする正規表現

「特定の文字から始まらない文字列」 にマッチする正規表現の例です。  以下の例では、Aから始まらない文字列にマッチする正規表現を示しています。 ^(?!A).*$ 私も正規表現の組み方で四苦八苦することがあります。以下の書籍は実践的に様々な正規表現のパターンを例示してくれているので、重宝しています。

ダイソーで買った200円のドライバーセットでHDDを分解

HDDの処分 最近は個人情報の問題もあって、HDDを処分する前にちゃんとデータの消去を気にすることも多くなってきました。消去方法としては大きく分けて下記の3つがあります。 データ消去ソフトでフォーマット HDD内部のプラッタを物理破壊 データ消去を行ってくれる専門の業者や家電量販店(Sofmapやビックカメラで実施していると思います。費用発生。)に持ち込み。 データ消去ソフトでのフォーマットは簡単ですが、欠点として「フォーマットに時間がかかる」「セクタ破損などで中途半端に壊れたディスクのフォーマットができない」などがあります。 またHDD内部のプラッタの物理破壊については、HDDを分解するために、通常のプラスやマイナスドライバーではなく、星形ネジに対応したトルクスドライバーが必要とのこともあって、少し面倒です。 筆者は今回、今後もHDDの廃棄をするだろうなあと思い、思い切って自分で分解して廃棄することにチャレンジしてみました。(家電量販店に持って行くよりも安くできないかというどケチ丸出しですw) HDDの星形ネジ こんなやつです。ちなみに写真はSeagateのST2000DL003というHDDで撮影しました。 トルクスドライバー というわけで、分解のために Amazonでトルクスドライバー を探しました。 調べると T8のもだと使えそう とのことで、いろいろと物色。 セットのものとか T8一本で立派なやつとか 色々あったのですが、HDD壊すだけで800円かぁ(←どケチ)、と思って購入を躊躇。 ネット上で調べると100円ショップのダイソーでも、トルクスドライバーを販売しているとの情報をキャッチ!近所のダイソーに行って、探したところ星形のヘッド交換に対応した精密ドライバーセットがありました。 プラスが10種類、マイナスが8種類、六角が6種類、星形が6種類(今回ほしかったもの)のセットで、何とお値段税抜き200円!、税抜き200円!と安かったので、ダメもとで購入しました。 結論から言うと 買って大正解 でした。 ダイソーの精密ドライバーセット こんな商品です! 星形対応のヘッドを装着するとこんな感じ。ドライバーのグリップもゴムで滑らない様になっていて使いやす...

SQLで特定の文字を組み合わせたランダムな文字列を生成

簡易的な方法として「指定した文字列からランダムに1文字選ぶ」を必要な文字の長さ分concat関数でつなげれば実現できます。 1文字ずつ文字を選ぶので、あまり性能もよくない上、セキュリティ的な観点からのランダム性も担保されていないので、あくまで開発中に必要になった時に使う程度が無難だと思います。 下記に英数字大文字小文字を含んだランダムな3文字の文字列を生成するクエリを示します。 # RAND関数で指定した文字列からランダムに1文字選択。 # 下記の例の62の部分はa~z、A~Z、1~9の文字数の合計値を入れた結果 SELECT CONCAT( SUBSTRING('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', FLOOR(RAND() * 62 + 1), 1), SUBSTRING('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', FLOOR(RAND() * 62 + 1), 1), SUBSTRING('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', FLOOR(RAND() * 62 + 1), 1) ) AS random_string;

PHPの配列(array)のメモリ使用量の考察

はじめに 最近PHP上に大量のデータをメモリ上に展開していたのですが、配列(array)の形式(連想配列 or 単純な配列)や配列の要素のデータ構造(数字、配列、文字列など)で大きくメモリ使用量に差が出てくることに気づき、簡単なプログラムを組んで調べてみました。 あくまで筆者の環境での結果なので、細かい数値は参考程度に見てください。 測定環境と方法 OS: Windows 10 PHP 7.4.5 (php-7.4.5-nts-Win32-vc15-x64) 配列に要素を追加するプログラムを書いて、PHPのmemory_get_usage(true)関数を使って実メモリ使用量を計測しました。 計測結果 No. 方式 1MB当たり作成できる 要素数 プログラム 補足 1 キーも値も整数の配列 (整数IDを想定) 28571 // 2,000,000 / 70MB $row = []; for($i = 0; $i < 2000000; $i++) { $row[] = $i; } No.2~6でテストしたプログラム中の要素数は200,000。これだけ一桁多い! 2 キーが文字列、値が整数の連想配列 8333 // 200,000 / 24MB $row = []; for($i = 0; $i < 200000; $i++) { $row[$i.'_key_string'] = $i; } キーの文字列が長い方がメモリ使用量多くなる。 3 キーが整数、値が連想配列の配列 DBから取得してきたデータを想定 2325 // 200,000 / 86MB $row = []; for($i = 0; $i < 200000; $i++) { row[] = ['id' => $i]; } 4 キーが整数、値が連想配列の配列(配列に複数の値を保持) DBから取得してきたデータを想定 2127 // 200,000 /...

ADODB.streamオブジェクトを使って文字列とByte配列を相互変換(Excel VBA)

ADODB.streamオブジェクトを使って文字列をByte配列に変換するコードのサンプルです。 ExcelVBAでADODB.streamを使う際には、 1. ExcelのMicrosoft Visual Basic エディタのメニューバーから「ツール->参照設定」とたどる。 2. 表示されたダイアログからMicrosoft ActiveX Data Objectsにチェックを入れる。 という手順が必要です。 文字列からByte配列へ Private Function ADOS_EncodeStringToByte(ByVal cset As String, ByRef strUni As String) As Byte() On Error GoTo e Dim objStm As ADODB.stream: Set objStm = New ADODB.stream objStm.Mode = adModeReadWrite objStm.Open objStm.Type = adTypeText objStm.Charset = cset objStm.WriteText strUni objStm.Position = 0 objStm.Type = adTypeBinary Select Case UCase(cset) Case "UNICODE", "UTF-16" objStm.Position = 2 Case "UTF-8" objStm.Position = 3 End Select ADOS_EncodeStringToByte = objStm.Read() objStm.Close Set objStm = Nothing Exit Function e: Debug.Print "Error occurred while encoding characters" & Err.Description If objStm Is No...

Visual Studio 2010 SP1のアンインストール

Visual Studio 2013に乗り換えるためにVisual Studio 2010をアンインストールしようとしたところで問題発生。。。 先にVisual Studio 2010本体をアンインストールした後、Visual Studio 2010 SP1をアンインストールできなくて困っていました。 Google先生で調べたところ、以下の情報が見つかり、書かれていた通り実施したところ無事Visual Studio 2010 SP1のアンインストールに成功しました。 How to uninstall/remove Visual Studio SP1 アンインストール手順は以下の通りです。 http://www.microsoft.com/en-gb/download/details.aspx?id=23691 からMicrosoft Visual Studio 2010 Service Pack 1 (Installer)をダウンロード VS10sp1-KB983509.exeというファイル名でダウンロードされる(はず)。 コマンドプロンプトから以下のコマンドを実行 (以下の例は、c:\tempにVS10sp1-KB983509.exeがある場合) c:\temp\VS10sp1-KB983509.exe /uninstall /force ダイアログが立ち上がるので、アンインストールを選択して次へ進めばOK!

PHPでファイルを指定した行数ごとに分割

ファイルを指定した行数ごとに分割するためには、Linuxのsplitコマンドを使えば簡単に実現できます。 PHPではexec関数にsplitコマンドを渡して実行すればよいですが、下記の弱点があります。 Linuxのコマンドに依存 (PHPの場合はほとんどLinux環境で動作させることが普通なのでそこまで問題にならないかも知れません)。 exec関数は慎重に引数を渡さないと、OSコマンドインジェクション脆弱性を引き起こす可能性がある。 そこで、今回はPHPでファイルを指定した行数ごとに分割するプログラムを書いてみました。 <?php class FileSplitter { private $lines; private $fileCount; public function split($filePath, $linesPerFile, $outputDir) { $this->fileCount = 0; $this->lines = null; $file = new \SplFileObject($filePath); $lineCount = 0; try{ while (!$file->eof()) { if($lineCount % $linesPerFile === 0) { $this->writeToFile($this->generateOutputFilePath($outputDir, $file)); } $this->lines[] = $file->fgets(); $lineCount++; } $this->writeToFile($this->generateOutpu...

zip圧縮されたsqlを解凍しながらMySQLに実行させる方法

mysqldumpなどで生成されたzip圧縮された巨大なsqlを解凍しながら、mysqlへ実行(リストア)する方法です。 パイプ(|)とリダイレクト(<)を駆使します。 gunzip < test.sql.gz | mysql -u USER -pPASSWORD -D DBNAME ちなみにmysqldumpの出力をzip圧縮する方法は下記になります。 mysqldump -u USER -pPASSWORD DBNAME | gzip > dump.sql.gz

JavaでCMYK Color SpaceのJPEGを読み込む

Read CMYK JPEG Image CMYKのJPEG画像をJavaで読む方法ではまったので、Google先生で色々調べて見ました。 Problem reading JPEG image using ImageIO.read(File file) によるとImageIOで読めないJPEGファイルはほとんどCMYK Color Spaceの画像のようです。 私の場合もまず読めないJPEGがあることでCMYKのJPEGであることに気がつきました。 という訳で、CMYKのJPEGをどうやって読み込めばいいのということで色々調べてみました。 以下のstackoverflowによると、基本的にまずCMYKのColor Spaceで読み込んで、それからRGB系のColor Spaceに変換することでJavaでも読み込みができるようです。 Pure Java alternative to JAI ImageIO for detecting CMYK images How do I convert images between CMYK and RGB in ColdFusion (Java)? How to convert from CMYK to RGB in Java correctly? ただし、このCMYKのColor Spaceインスタンスを作るのが結構面倒です。 前述のstackoverflowによると、以下の方法があるようです。 CMYKのColorSpaceをSanselanライブラリを使って画像から抜き出す ICC_Profile iccProfile = Sanselan.getICCProfile(new File("filename.jpg")); ColorSpace cs = new ICC_ColorSpace(iccProfile); 自分でCMYKColorSpaceクラスを定義して、インスタンス化する iccプロファイルから、ColorSpaceインスタンスを生成する。ただしiccプロファイルはどこかから自前に用意する必要があります。 ICC_Profile iccProfileCYMK = ICC_Profile.getInstance(new FileInputStre...